Skip to content

Commit 969f665

Browse files
First working implementation
1 parent 110c2e5 commit 969f665

16 files changed

+350
-183
lines changed

src/QuantumToolbox.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ import SciMLBase:
3232
ContinuousCallback,
3333
DiscreteCallback
3434
import StochasticDiffEq: StochasticDiffEqAlgorithm, SRA1
35-
import SciMLOperators: MatrixOperator
35+
import SciMLOperators:
36+
AbstractSciMLOperator, MatrixOperator, ScalarOperator, cache_operator, update_coefficients!, concretize
3637
import LinearSolve: LinearProblem, SciMLLinearSolveAlgorithm, KrylovJL_MINRES, KrylovJL_GMRES
3738
import DiffEqBase: get_tstops
3839
import DiffEqCallbacks: PeriodicCallback, PresetTimeCallback, TerminateSteadyState
@@ -63,6 +64,7 @@ include("linear_maps.jl")
6364

6465
# Quantum Object
6566
include("qobj/quantum_object.jl")
67+
include("qobj/quantum_object_evo.jl")
6668
include("qobj/boolean_functions.jl")
6769
include("qobj/arithmetic_and_attributes.jl")
6870
include("qobj/eigsolve.jl")

src/qobj/arithmetic_and_attributes.jl

Lines changed: 83 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -36,84 +36,82 @@ end
3636

3737
for op in (:(+), :(-), :(*))
3838
@eval begin
39-
function LinearAlgebra.$op(
40-
A::QuantumObject{<:AbstractArray{T1},OpType},
41-
B::QuantumObject{<:AbstractArray{T2},OpType},
42-
) where {T1,T2,OpType<:QuantumObjectType}
39+
function LinearAlgebra.$op(A::AbstractQuantumObject, B::AbstractQuantumObject)
4340
A.dims != B.dims &&
44-
throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
41+
throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
42+
if A isa QuantumObjectEvolution || B isa QuantumObjectEvolution
43+
return QuantumObjectEvolution($(op)(A.data, B.data), A.type, A.dims)
44+
end
4545
return QuantumObject($(op)(A.data, B.data), A.type, A.dims)
4646
end
47-
LinearAlgebra.$op(A::QuantumObject{<:AbstractArray{T}}) where {T} = QuantumObject($(op)(A.data), A.type, A.dims)
47+
LinearAlgebra.$op(A::AbstractQuantumObject) = get_typename_wrapper(A)($(op)(A.data), A.type, A.dims)
4848

49-
LinearAlgebra.$op(n::T1, A::QuantumObject{<:AbstractArray{T2}}) where {T1<:Number,T2} =
50-
QuantumObject($(op)(n * I, A.data), A.type, A.dims)
51-
LinearAlgebra.$op(A::QuantumObject{<:AbstractArray{T1}}, n::T2) where {T1,T2<:Number} =
52-
QuantumObject($(op)(A.data, n * I), A.type, A.dims)
49+
LinearAlgebra.$op(n::T, A::AbstractQuantumObject) where {T<:Number} =
50+
get_typename_wrapper(A)($(op)(n * I, A.data), A.type, A.dims)
51+
LinearAlgebra.$op(A::AbstractQuantumObject, n::T) where {T<:Number} =
52+
get_typename_wrapper(A)($(op)(A.data, n * I), A.type, A.dims)
5353
end
5454
end
5555

5656
function LinearAlgebra.:(*)(
57-
A::QuantumObject{<:AbstractArray{T1},OperatorQuantumObject},
58-
B::QuantumObject{<:AbstractArray{T2},KetQuantumObject},
59-
) where {T1,T2}
60-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
57+
A::AbstractQuantumObject{DT1,OperatorQuantumObject},
58+
B::QuantumObject{DT2,KetQuantumObject},
59+
) where {DT1,DT2}
60+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
6161
return QuantumObject(A.data * B.data, Ket, A.dims)
6262
end
6363
function LinearAlgebra.:(*)(
64-
A::QuantumObject{<:AbstractArray{T1},BraQuantumObject},
65-
B::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject},
66-
) where {T1,T2}
67-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
64+
A::QuantumObject{DT1,BraQuantumObject},
65+
B::AbstractQuantumObject{DT2,OperatorQuantumObject},
66+
) where {DT1,DT2}
67+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
6868
return QuantumObject(A.data * B.data, Bra, A.dims)
6969
end
7070
function LinearAlgebra.:(*)(
71-
A::QuantumObject{<:AbstractArray{T1},KetQuantumObject},
72-
B::QuantumObject{<:AbstractArray{T2},BraQuantumObject},
73-
) where {T1,T2}
74-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
71+
A::QuantumObject{DT1,KetQuantumObject},
72+
B::QuantumObject{DT2,BraQuantumObject},
73+
) where {DT1,DT2}
74+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
7575
return QuantumObject(A.data * B.data, Operator, A.dims)
7676
end
7777
function LinearAlgebra.:(*)(
78-
A::QuantumObject{<:AbstractArray{T1},BraQuantumObject},
79-
B::QuantumObject{<:AbstractArray{T2},KetQuantumObject},
80-
) where {T1,T2}
81-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
78+
A::QuantumObject{DT1,BraQuantumObject},
79+
B::QuantumObject{DT2,KetQuantumObject},
80+
) where {DT1,DT2}
81+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
8282
return A.data * B.data
8383
end
8484
function LinearAlgebra.:(*)(
85-
A::QuantumObject{<:AbstractArray{T1},SuperOperatorQuantumObject},
86-
B::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject},
87-
) where {T1,T2}
88-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
85+
A::AbstractQuantumObject{DT1,SuperOperatorQuantumObject},
86+
B::QuantumObject{DT2,OperatorQuantumObject},
87+
) where {DT1,DT2}
88+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
8989
return QuantumObject(vec2mat(A.data * mat2vec(B.data)), Operator, A.dims)
9090
end
9191
function LinearAlgebra.:(*)(
92-
A::QuantumObject{<:AbstractArray{T1},OperatorBraQuantumObject},
93-
B::QuantumObject{<:AbstractArray{T2},OperatorKetQuantumObject},
94-
) where {T1,T2}
95-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
92+
A::QuantumObject{DT1,OperatorBraQuantumObject},
93+
B::QuantumObject{DT2,OperatorKetQuantumObject},
94+
) where {DT1,DT2}
95+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
9696
return A.data * B.data
9797
end
9898
function LinearAlgebra.:(*)(
99-
A::QuantumObject{<:AbstractArray{T1},SuperOperatorQuantumObject},
100-
B::QuantumObject{<:AbstractArray{T2},OperatorKetQuantumObject},
101-
) where {T1,T2}
102-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
99+
A::AbstractQuantumObject{DT1,SuperOperatorQuantumObject},
100+
B::QuantumObject{DT2,OperatorKetQuantumObject},
101+
) where {DT1,DT2}
102+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
103103
return QuantumObject(A.data * B.data, OperatorKet, A.dims)
104104
end
105105
function LinearAlgebra.:(*)(
106106
A::QuantumObject{<:AbstractArray{T1},OperatorBraQuantumObject},
107-
B::QuantumObject{<:AbstractArray{T2},SuperOperatorQuantumObject},
107+
B::AbstractQuantumObject{<:AbstractArray{T2},SuperOperatorQuantumObject},
108108
) where {T1,T2}
109-
A.dims != B.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))
109+
A.dims != B.dims && throw(DimensionMismatch("The two quantum object don't have the same Hilbert dimension."))
110110
return QuantumObject(A.data * B.data, OperatorBra, A.dims)
111111
end
112112

113-
LinearAlgebra.:(^)(A::QuantumObject{<:AbstractArray{T}}, n::T1) where {T,T1<:Number} =
114-
QuantumObject(^(A.data, n), A.type, A.dims)
115-
LinearAlgebra.:(/)(A::QuantumObject{<:AbstractArray{T}}, n::T1) where {T,T1<:Number} =
116-
QuantumObject(/(A.data, n), A.type, A.dims)
113+
LinearAlgebra.:(^)(A::QuantumObject{DT}, n::T) where {DT,T<:Number} = QuantumObject(^(A.data, n), A.type, A.dims)
114+
LinearAlgebra.:(/)(A::QuantumObject{DT}, n::T) where {DT,T<:Number} = QuantumObject(/(A.data, n), A.type, A.dims)
117115

118116
@doc raw"""
119117
dot(A::QuantumObject, B::QuantumObject)
@@ -125,93 +123,91 @@ Note that `A` and `B` should be [`Ket`](@ref) or [`OperatorKet`](@ref)
125123
`A ⋅ B` (where `⋅` can be typed by tab-completing `\cdot` in the REPL) is a synonym for `dot(A, B)`
126124
"""
127125
function LinearAlgebra.dot(
128-
A::QuantumObject{<:AbstractArray{T1},OpType},
129-
B::QuantumObject{<:AbstractArray{T2},OpType},
130-
) where {T1<:Number,T2<:Number,OpType<:Union{KetQuantumObject,OperatorKetQuantumObject}}
126+
A::QuantumObject{DT1,OpType},
127+
B::QuantumObject{DT2,OpType},
128+
) where {DT1,DT2,OpType<:Union{KetQuantumObject,OperatorKetQuantumObject}}
131129
A.dims != B.dims && throw(DimensionMismatch("The quantum objects are not of the same Hilbert dimension."))
132130
return LinearAlgebra.dot(A.data, B.data)
133131
end
134132

135133
@doc raw"""
136-
dot(i::QuantumObject, A::QuantumObject j::QuantumObject)
134+
dot(i::QuantumObject, A::AbstractQuantumObject j::QuantumObject)
137135
138-
Compute the generalized dot product `dot(i, A*j)` between three [`QuantumObject`](@ref): ``\langle i | \hat{A} | j \rangle``
136+
Compute the generalized dot product `dot(i, A*j)` between three [`AbstractQuantumObject`](@ref): ``\langle i | \hat{A} | j \rangle``
139137
140138
Supports the following inputs:
141139
- `A` is in the type of [`Operator`](@ref), with `i` and `j` are both [`Ket`](@ref).
142140
- `A` is in the type of [`SuperOperator`](@ref), with `i` and `j` are both [`OperatorKet`](@ref)
143141
"""
144142
function LinearAlgebra.dot(
145-
i::QuantumObject{<:AbstractArray{T1},KetQuantumObject},
146-
A::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject},
147-
j::QuantumObject{<:AbstractArray{T3},KetQuantumObject},
148-
) where {T1<:Number,T2<:Number,T3<:Number}
143+
i::QuantumObject{DT1,KetQuantumObject},
144+
A::AbstractQuantumObject{DT2,OperatorQuantumObject},
145+
j::QuantumObject{DT3,KetQuantumObject},
146+
) where {DT1,DT2,DT3}
149147
((i.dims != A.dims) || (A.dims != j.dims)) &&
150148
throw(DimensionMismatch("The quantum objects are not of the same Hilbert dimension."))
151149
return LinearAlgebra.dot(i.data, A.data, j.data)
152150
end
153151
function LinearAlgebra.dot(
154-
i::QuantumObject{<:AbstractArray{T1},OperatorKetQuantumObject},
155-
A::QuantumObject{<:AbstractArray{T2},SuperOperatorQuantumObject},
156-
j::QuantumObject{<:AbstractArray{T3},OperatorKetQuantumObject},
157-
) where {T1<:Number,T2<:Number,T3<:Number}
152+
i::QuantumObject{DT1,OperatorKetQuantumObject},
153+
A::AbstractQuantumObject{DT2,SuperOperatorQuantumObject},
154+
j::QuantumObject{DT3,OperatorKetQuantumObject},
155+
) where {DT1,DT2,DT3}
158156
((i.dims != A.dims) || (A.dims != j.dims)) &&
159157
throw(DimensionMismatch("The quantum objects are not of the same Hilbert dimension."))
160158
return LinearAlgebra.dot(i.data, A.data, j.data)
161159
end
162160

163161
@doc raw"""
164-
conj(A::QuantumObject)
162+
conj(A::AbstractQuantumObject)
165163
166-
Return the element-wise complex conjugation of the [`QuantumObject`](@ref).
164+
Return the element-wise complex conjugation of the [`AbstractQuantumObject`](@ref).
167165
"""
168-
Base.conj(A::QuantumObject{<:AbstractArray{T}}) where {T} = QuantumObject(conj(A.data), A.type, A.dims)
166+
Base.conj(A::AbstractQuantumObject) = get_typename_wrapper(A)(conj(A.data), A.type, A.dims)
169167

170168
@doc raw"""
171-
transpose(A::QuantumObject)
169+
transpose(A::AbstractQuantumObject)
172170
173-
Lazy matrix transpose of the [`QuantumObject`](@ref).
171+
Lazy matrix transpose of the [`AbstractQuantumObject`](@ref).
174172
"""
175173
LinearAlgebra.transpose(
176-
A::QuantumObject{<:AbstractArray{T},OpType},
177-
) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
178-
QuantumObject(transpose(A.data), A.type, A.dims)
174+
A::AbstractQuantumObject{DT,OpType},
175+
) where {DT,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
176+
get_typename_wrapper(A)(transpose(A.data), A.type, A.dims)
179177

180178
@doc raw"""
181179
A'
182-
adjoint(A::QuantumObject)
180+
adjoint(A::AbstractQuantumObject)
183181
184-
Lazy adjoint (conjugate transposition) of the [`QuantumObject`](@ref)
182+
Lazy adjoint (conjugate transposition) of the [`AbstractQuantumObject`](@ref)
185183
186184
Note that `A'` is a synonym for `adjoint(A)`
187185
"""
188186
LinearAlgebra.adjoint(
189-
A::QuantumObject{<:AbstractArray{T},OpType},
190-
) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
191-
QuantumObject(adjoint(A.data), A.type, A.dims)
192-
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},KetQuantumObject}) where {T} =
193-
QuantumObject(adjoint(A.data), Bra, A.dims)
194-
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},BraQuantumObject}) where {T} =
195-
QuantumObject(adjoint(A.data), Ket, A.dims)
196-
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},OperatorKetQuantumObject}) where {T} =
187+
A::AbstractQuantumObject{DT,OpType},
188+
) where {DT,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
189+
get_typename_wrapper(A)(adjoint(A.data), A.type, A.dims)
190+
LinearAlgebra.adjoint(A::QuantumObject{DT,KetQuantumObject}) where {DT} = QuantumObject(adjoint(A.data), Bra, A.dims)
191+
LinearAlgebra.adjoint(A::QuantumObject{DT,BraQuantumObject}) where {DT} = QuantumObject(adjoint(A.data), Ket, A.dims)
192+
LinearAlgebra.adjoint(A::QuantumObject{DT,OperatorKetQuantumObject}) where {DT} =
197193
QuantumObject(adjoint(A.data), OperatorBra, A.dims)
198-
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},OperatorBraQuantumObject}) where {T} =
194+
LinearAlgebra.adjoint(A::QuantumObject{DT,OperatorBraQuantumObject}) where {DT} =
199195
QuantumObject(adjoint(A.data), OperatorKet, A.dims)
200196

201197
@doc raw"""
202-
inv(A::QuantumObject)
198+
inv(A::AbstractQuantumObject)
203199
204-
Matrix inverse of the [`QuantumObject`](@ref)
200+
Matrix inverse of the [`AbstractQuantumObject`](@ref). If `A` is a [`QuantumObjectEvolution`](@ref), the inverse is computed at the last computed time.
205201
"""
206202
LinearAlgebra.inv(
207-
A::QuantumObject{<:AbstractArray{T},OpType},
208-
) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
203+
A::AbstractQuantumObject{DT,OpType},
204+
) where {DT,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
209205
QuantumObject(sparse(inv(Matrix(A.data))), A.type, A.dims)
210206

211207
LinearAlgebra.Hermitian(
212-
A::QuantumObject{<:AbstractArray{T},OpType},
208+
A::QuantumObject{DT,OpType},
213209
uplo::Symbol = :U,
214-
) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
210+
) where {DT,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
215211
QuantumObject(Hermitian(A.data, uplo), A.type, A.dims)
216212

217213
@doc raw"""
@@ -436,8 +432,8 @@ Matrix sine of [`QuantumObject`](@ref), defined as
436432
Note that this function only supports for [`Operator`](@ref) and [`SuperOperator`](@ref)
437433
"""
438434
LinearAlgebra.sin(
439-
A::QuantumObject{<:AbstractMatrix{T},ObjType},
440-
) where {T,ObjType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} = (exp(1im * A) - exp(-1im * A)) / 2im
435+
A::QuantumObject{DT,ObjType},
436+
) where {DT,ObjType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} = (exp(1im * A) - exp(-1im * A)) / 2im
441437

442438
@doc raw"""
443439
cos(A::QuantumObject)
@@ -659,11 +655,11 @@ tidyup!(A::AbstractArray{T}, tol::T2 = 1e-14) where {T,T2<:Real} =
659655
@. A = T(abs(real(A)) > tol) * real(A) + 1im * T(abs(imag(A)) > tol) * imag(A)
660656

661657
@doc raw"""
662-
get_data(A::QuantumObject)
658+
get_data(A::AbstractQuantumObject)
663659
664-
Returns the data of a QuantumObject.
660+
Returns the data of a [`AbstractQuantumObject`](@ref).
665661
"""
666-
get_data(A::QuantumObject) = A.data
662+
get_data(A::AbstractQuantumObject) = A.data
667663

668664
@doc raw"""
669665
get_coherence(ψ::QuantumObject)

0 commit comments

Comments
 (0)