Skip to content

Commit f17ee1e

Browse files
committed
Add test_bases from QuantumOpticsBase and reorganize a bit
1 parent f22adb7 commit f17ee1e

File tree

12 files changed

+203
-135
lines changed

12 files changed

+203
-135
lines changed

src/QuantumInterface.jl

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,33 @@
11
module QuantumInterface
22

3-
import Base: ==, +, -, *, /, ^, length, one, exp, conj, conj!, transpose, copy
4-
import LinearAlgebra: tr, ishermitian, norm, normalize, normalize!
5-
import Base: show, summary
6-
import SparseArrays: sparse, spzeros, AbstractSparseMatrix # TODO move to an extension
3+
##
4+
# Basis specific
5+
##
6+
7+
"""
8+
basis(a)
9+
10+
Return the basis of an object.
11+
12+
If it's ambiguous, e.g. if an operator has a different left and right basis,
13+
an [`IncompatibleBases`](@ref) error is thrown.
14+
"""
15+
function basis end
16+
17+
##
18+
# Standard methods
19+
##
720

821
function apply! end
922

1023
function dagger end
1124

25+
"""
26+
directsum(x, y, z...)
27+
28+
Direct sum of the given objects. Alternatively, the unicode
29+
symbol ⊕ (\\oplus) can be used.
30+
"""
1231
function directsum end
1332
const = directsum
1433
directsum() = GenericBasis(0)
@@ -86,8 +105,9 @@ function squeeze end
86105
function wigner end
87106

88107

89-
include("bases.jl")
90108
include("abstract_types.jl")
109+
include("bases.jl")
110+
include("show.jl")
91111

92112
include("linalg.jl")
93113
include("tensor.jl")

src/abstract_types.jl

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
"""
2+
Abstract base class for all specialized bases.
3+
4+
The Basis class is meant to specify a basis of the Hilbert space of the
5+
studied system. Besides basis specific information all subclasses must
6+
implement a shape variable which indicates the dimension of the used
7+
Hilbert space. For a spin-1/2 Hilbert space this would be the
8+
vector `[2]`. A system composed of two spins would then have a
9+
shape vector `[2 2]`.
10+
11+
Composite systems can be defined with help of the [`CompositeBasis`](@ref)
12+
class.
13+
"""
14+
abstract type Basis end
15+
116
"""
217
Abstract base class for `Bra` and `Ket` states.
318
@@ -38,20 +53,3 @@ A_{br_1,br_2} = B_{bl_1,bl_2} S_{(bl_1,bl_2) ↔ (br_1,br_2)}
3853
```
3954
"""
4055
abstract type AbstractSuperOperator{B1,B2} end
41-
42-
function summary(stream::IO, x::AbstractOperator)
43-
print(stream, "$(typeof(x).name.name)(dim=$(length(x.basis_l))x$(length(x.basis_r)))\n")
44-
if samebases(x)
45-
print(stream, " basis: ")
46-
show(stream, basis(x))
47-
else
48-
print(stream, " basis left: ")
49-
show(stream, x.basis_l)
50-
print(stream, "\n basis right: ")
51-
show(stream, x.basis_r)
52-
end
53-
end
54-
55-
show(stream::IO, x::AbstractOperator) = summary(stream, x)
56-
57-
traceout!(s::StateVector, i) = ptrace(s,i)

src/bases.jl

Lines changed: 3 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,10 @@
1-
"""
2-
Abstract base class for all specialized bases.
3-
4-
The Basis class is meant to specify a basis of the Hilbert space of the
5-
studied system. Besides basis specific information all subclasses must
6-
implement a shape variable which indicates the dimension of the used
7-
Hilbert space. For a spin-1/2 Hilbert space this would be the
8-
vector `[2]`. A system composed of two spins would then have a
9-
shape vector `[2 2]`.
10-
11-
Composite systems can be defined with help of the [`CompositeBasis`](@ref)
12-
class.
13-
"""
14-
abstract type Basis end
15-
161
"""
172
length(b::Basis)
183
194
Total dimension of the Hilbert space.
205
"""
216
Base.length(b::Basis) = prod(b.shape)
227

23-
"""
24-
basis(a)
25-
26-
Return the basis of an object.
27-
28-
If it's ambiguous, e.g. if an operator has a different left and right basis,
29-
an [`IncompatibleBases`](@ref) error is thrown.
30-
"""
31-
function basis end
32-
338

349
"""
3510
GenericBasis(N)
@@ -366,9 +341,9 @@ SumBasis(shape, bases::Vector) = (tmp = (bases...,); SumBasis(shape, tmp))
366341
SumBasis(bases::Vector) = SumBasis((bases...,))
367342
SumBasis(bases::Basis...) = SumBasis((bases...,))
368343

369-
==(b1::T, b2::T) where T<:SumBasis = equal_shape(b1.shape, b2.shape)
370-
==(b1::SumBasis, b2::SumBasis) = false
371-
length(b::SumBasis) = sum(b.shape)
344+
Base.:(==)(b1::T, b2::T) where T<:SumBasis = equal_shape(b1.shape, b2.shape)
345+
Base.:(==)(b1::SumBasis, b2::SumBasis) = false
346+
Base.length(b::SumBasis) = sum(b.shape)
372347

373348
"""
374349
directsum(b1::Basis, b2::Basis)
@@ -393,62 +368,3 @@ function directsum(b1::SumBasis, b2::SumBasis)
393368
bases = [b1.bases...;b2.bases...]
394369
return SumBasis(shape, (bases...,))
395370
end
396-
397-
embed(b::SumBasis, indices, ops) = embed(b, b, indices, ops)
398-
399-
##
400-
# show methods
401-
##
402-
403-
function show(stream::IO, x::GenericBasis)
404-
if length(x.shape) == 1
405-
write(stream, "Basis(dim=$(x.shape[1]))")
406-
else
407-
s = replace(string(x.shape), " " => "")
408-
write(stream, "Basis(shape=$s)")
409-
end
410-
end
411-
412-
function show(stream::IO, x::CompositeBasis)
413-
write(stream, "[")
414-
for i in 1:length(x.bases)
415-
show(stream, x.bases[i])
416-
if i != length(x.bases)
417-
write(stream, "")
418-
end
419-
end
420-
write(stream, "]")
421-
end
422-
423-
function show(stream::IO, x::SpinBasis)
424-
d = denominator(x.spinnumber)
425-
n = numerator(x.spinnumber)
426-
if d == 1
427-
write(stream, "Spin($n)")
428-
else
429-
write(stream, "Spin($n/$d)")
430-
end
431-
end
432-
433-
function show(stream::IO, x::FockBasis)
434-
if iszero(x.offset)
435-
write(stream, "Fock(cutoff=$(x.N))")
436-
else
437-
write(stream, "Fock(cutoff=$(x.N), offset=$(x.offset))")
438-
end
439-
end
440-
441-
function show(stream::IO, x::NLevelBasis)
442-
write(stream, "NLevel(N=$(x.N))")
443-
end
444-
445-
function show(stream::IO, x::SumBasis)
446-
write(stream, "[")
447-
for i in 1:length(x.bases)
448-
show(stream, x.bases[i])
449-
if i != length(x.bases)
450-
write(stream, "")
451-
end
452-
end
453-
write(stream, "]")
454-
end

src/embed_permute.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
6767
ops_sb = [x[2] for x in idxop_sb]
6868

6969
for (idxsb, opsb) in zip(indices_sb, ops_sb)
70-
(opsb.basis_l == basis_l.bases[idxsb]) || throw(IncompatibleBases())
71-
(opsb.basis_r == basis_r.bases[idxsb]) || throw(IncompatibleBases())
70+
(opsb.basis_l == basis_l.bases[idxsb]) || throw(IncompatibleBases()) # FIXME issue #12
71+
(opsb.basis_r == basis_r.bases[idxsb]) || throw(IncompatibleBases()) # FIXME issue #12
7272
end
7373

7474
S = length(operators) > 0 ? mapreduce(eltype, promote_type, operators) : Any
@@ -83,6 +83,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
8383
return embed_op
8484
end
8585

86+
embed(b::SumBasis, indices, ops) = embed(b, b, indices, ops)
87+
8688
permutesystems(a::AbstractOperator, perm) = arithmetic_unary_error("Permutations of subsystems", a)
8789

8890
nsubsystems(s::AbstractKet) = nsubsystems(basis(s))

src/identityoperator.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
one(x::Union{<:Basis,<:AbstractOperator}) = identityoperator(x)
1+
Base.one(x::Union{<:Basis,<:AbstractOperator}) = identityoperator(x)
22

33
"""
44
identityoperator(a::Basis[, b::Basis])
@@ -22,4 +22,4 @@ identityoperator(::Type{T}, ::Type{Any}, b1::Basis, b2::Basis) where T<:Abstract
2222
identityoperator(b1::Basis, b2::Basis) = identityoperator(ComplexF64, b1, b2)
2323

2424
"""Prepare the identity superoperator over a given space."""
25-
function identitysuperoperator end
25+
function identitysuperoperator end

src/julia_base.jl

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Base: +, -, *, /, ^, length, exp, conj, conj!, adjoint, transpose, copy
2+
13
# Common error messages
24
arithmetic_unary_error(funcname, x::AbstractOperator) = throw(ArgumentError("$funcname is not defined for this type of operator: $(typeof(x)).\nTry to convert to another operator type first with e.g. dense() or sparse()."))
35
arithmetic_binary_error(funcname, a::AbstractOperator, b::AbstractOperator) = throw(ArgumentError("$funcname is not defined for this combination of types of operators: $(typeof(a)), $(typeof(b)).\nTry to convert to a common operator type first with e.g. dense() or sparse()."))
@@ -8,33 +10,33 @@ addnumbererror() = throw(ArgumentError("Can't add or subtract a number and an op
810
# States
911
##
1012

11-
-(a::T) where {T<:StateVector} = T(a.basis, -a.data)
13+
-(a::T) where {T<:StateVector} = T(a.basis, -a.data) # FIXME issue #12
1214
*(a::StateVector, b::Number) = b*a
13-
copy(a::T) where {T<:StateVector} = T(a.basis, copy(a.data))
14-
length(a::StateVector) = length(a.basis)::Int
15-
basis(a::StateVector) = a.basis
15+
copy(a::T) where {T<:StateVector} = T(a.basis, copy(a.data)) # FIXME issue #12
16+
length(a::StateVector) = length(a.basis)::Int # FIXME issue #12
17+
basis(a::StateVector) = a.basis # FIXME issue #12
1618
directsum(x::StateVector...) = reduce(directsum, x)
19+
adjoint(a::StateVector) = dagger(a)
20+
21+
1722

1823
# Array-like functions
19-
Base.size(x::StateVector) = size(x.data)
20-
@inline Base.axes(x::StateVector) = axes(x.data)
24+
Base.size(x::StateVector) = size(x.data) # FIXME issue #12
25+
@inline Base.axes(x::StateVector) = axes(x.data) # FIXME issue #12
2126
Base.ndims(x::StateVector) = 1
2227
Base.ndims(::Type{<:StateVector}) = 1
23-
Base.eltype(x::StateVector) = eltype(x.data)
28+
Base.eltype(x::StateVector) = eltype(x.data) # FIXME issue #12
2429

2530
# Broadcasting
2631
Base.broadcastable(x::StateVector) = x
2732

28-
Base.adjoint(a::StateVector) = dagger(a)
29-
30-
3133
##
3234
# Operators
3335
##
3436

35-
length(a::AbstractOperator) = length(a.basis_l)::Int*length(a.basis_r)::Int
36-
basis(a::AbstractOperator) = (check_samebases(a); a.basis_l)
37-
basis(a::AbstractSuperOperator) = (check_samebases(a); a.basis_l[1])
37+
length(a::AbstractOperator) = length(a.basis_l)::Int*length(a.basis_r)::Int # FIXME issue #12
38+
basis(a::AbstractOperator) = (check_samebases(a); a.basis_l) # FIXME issue #12
39+
basis(a::AbstractSuperOperator) = (check_samebases(a); a.basis_l[1]) # FIXME issue #12
3840

3941
# Ensure scalar broadcasting
4042
Base.broadcastable(x::AbstractOperator) = Ref(x)
@@ -60,14 +62,17 @@ Operator exponential.
6062
"""
6163
exp(op::AbstractOperator) = throw(ArgumentError("exp() is not defined for this type of operator: $(typeof(op)).\nTry to convert to dense operator first with dense()."))
6264

63-
Base.size(op::AbstractOperator) = (length(op.basis_l),length(op.basis_r))
65+
Base.size(op::AbstractOperator) = (length(op.basis_l),length(op.basis_r)) # FIXME issue #12
6466
function Base.size(op::AbstractOperator, i::Int)
6567
i < 1 && throw(ErrorException("dimension index is < 1"))
6668
i > 2 && return 1
67-
i==1 ? length(op.basis_l) : length(op.basis_r)
69+
i==1 ? length(op.basis_l) : length(op.basis_r) # FIXME issue #12
6870
end
6971

70-
Base.adjoint(a::AbstractOperator) = dagger(a)
72+
adjoint(a::AbstractOperator) = dagger(a)
73+
74+
transpose(a::AbstractOperator) = arithmetic_unary_error("Transpose", a)
75+
7176

7277
conj(a::AbstractOperator) = arithmetic_unary_error("Complex conjugate", a)
7378
conj!(a::AbstractOperator) = conj(a::AbstractOperator)

src/julia_linalg.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import LinearAlgebra: tr, ishermitian, norm, normalize, normalize!
2+
13
"""
24
ishermitian(op::AbstractOperator)
35

src/linalg.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
samebases(a::AbstractOperator) = samebases(a.basis_l, a.basis_r)::Bool
2-
samebases(a::AbstractOperator, b::AbstractOperator) = samebases(a.basis_l, b.basis_l)::Bool && samebases(a.basis_r, b.basis_r)::Bool
3-
check_samebases(a::Union{AbstractOperator, AbstractSuperOperator}) = check_samebases(a.basis_l, a.basis_r)
4-
multiplicable(a::AbstractOperator, b::AbstractOperator) = multiplicable(a.basis_r, b.basis_l)
1+
samebases(a::AbstractOperator) = samebases(a.basis_l, a.basis_r)::Bool # FIXME issue #12
2+
samebases(a::AbstractOperator, b::AbstractOperator) = samebases(a.basis_l, b.basis_l)::Bool && samebases(a.basis_r, b.basis_r)::Bool # FIXME issue #12
3+
check_samebases(a::Union{AbstractOperator, AbstractSuperOperator}) = check_samebases(a.basis_l, a.basis_r) # FIXME issue #12
4+
multiplicable(a::AbstractOperator, b::AbstractOperator) = multiplicable(a.basis_r, b.basis_l) # FIXME issue #12
55
dagger(a::AbstractOperator) = arithmetic_unary_error("Hermitian conjugate", a)
6-
transpose(a::AbstractOperator) = arithmetic_unary_error("Transpose", a)
76
directsum(a::AbstractOperator...) = reduce(directsum, a)
87
ptrace(a::AbstractOperator, index) = arithmetic_unary_error("Partial trace", a)
98
_index_complement(b::CompositeBasis, indices) = complement(length(b.bases), indices)
109
reduced(a, indices) = ptrace(a, _index_complement(basis(a), indices))
10+
traceout!(s::StateVector, i) = ptrace(s,i)

src/show.jl

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import Base: show, summary
2+
3+
function summary(stream::IO, x::AbstractOperator)
4+
print(stream, "$(typeof(x).name.name)(dim=$(length(x.basis_l))x$(length(x.basis_r)))\n")
5+
if samebases(x)
6+
print(stream, " basis: ")
7+
show(stream, basis(x))
8+
else
9+
print(stream, " basis left: ")
10+
show(stream, x.basis_l)
11+
print(stream, "\n basis right: ")
12+
show(stream, x.basis_r)
13+
end
14+
end
15+
16+
show(stream::IO, x::AbstractOperator) = summary(stream, x)
17+
18+
function show(stream::IO, x::GenericBasis)
19+
if length(x.shape) == 1
20+
write(stream, "Basis(dim=$(x.shape[1]))")
21+
else
22+
s = replace(string(x.shape), " " => "")
23+
write(stream, "Basis(shape=$s)")
24+
end
25+
end
26+
27+
function show(stream::IO, x::CompositeBasis)
28+
write(stream, "[")
29+
for i in 1:length(x.bases)
30+
show(stream, x.bases[i])
31+
if i != length(x.bases)
32+
write(stream, "")
33+
end
34+
end
35+
write(stream, "]")
36+
end
37+
38+
function show(stream::IO, x::SpinBasis)
39+
d = denominator(x.spinnumber)
40+
n = numerator(x.spinnumber)
41+
if d == 1
42+
write(stream, "Spin($n)")
43+
else
44+
write(stream, "Spin($n/$d)")
45+
end
46+
end
47+
48+
function show(stream::IO, x::FockBasis)
49+
if iszero(x.offset)
50+
write(stream, "Fock(cutoff=$(x.N))")
51+
else
52+
write(stream, "Fock(cutoff=$(x.N), offset=$(x.offset))")
53+
end
54+
end
55+
56+
function show(stream::IO, x::NLevelBasis)
57+
write(stream, "NLevel(N=$(x.N))")
58+
end
59+
60+
function show(stream::IO, x::SumBasis)
61+
write(stream, "[")
62+
for i in 1:length(x.bases)
63+
show(stream, x.bases[i])
64+
if i != length(x.bases)
65+
write(stream, "")
66+
end
67+
end
68+
write(stream, "]")
69+
end

0 commit comments

Comments
 (0)