• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iitis / QuantumInformation.jl / 20928556968

12 Jan 2026 05:21PM UTC coverage: 93.287% (+0.8%) from 92.445%
20928556968

Pull #108

github

web-flow
Merge 1343d6c95 into cc74f1371
Pull Request #108: Support for arbitrary element types and sparse matrices

550 of 599 new or added lines in 17 files covered. (91.82%)

2 existing lines in 1 file now uncovered.

931 of 998 relevant lines covered (93.29%)

143.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.16
/src/matrixbases.jl
1
import .Base: length, iterate
2
using SparseArrays
3

4
export AbstractMatrixBasisIterator,
5
    HermitianBasisIterator,
6
    ElementaryBasisIterator,
7
    AbstractBasis,
8
    AbstractMatrixBasis,
9
    HermitianBasis,
10
    ElementaryBasis,
11
    ChannelBasisIterator,
12
    AbstractChannelBasis,
13
    ChannelBasis,
14
    hermitianbasis,
15
    channelbasis,
16
    represent,
17
    combine
18

19
abstract type AbstractMatrixBasisIterator{T <: AbstractMatrix} end
20
struct HermitianBasisIterator{T} <: AbstractMatrixBasisIterator{T}
21
    dim::Int
84✔
22
end
23

24
struct ElementaryBasisIterator{T} <: AbstractMatrixBasisIterator{T}
25
    idim::Int
3✔
26
    odim::Int
27
end
28

29
abstract type AbstractBasis end
30
abstract type AbstractMatrixBasis{T} <: AbstractBasis where {T <: AbstractMatrix{<:Number}} end
31

32
struct HermitianBasis{T} <: AbstractMatrixBasis{T}
33
    iterator::HermitianBasisIterator{T}
34

35
    function HermitianBasis{T}(dim::Integer) where {T <: AbstractMatrix{<:Number}}
33✔
36
        return new(HermitianBasisIterator{T}(dim))
33✔
37
    end
38
end
39

40
struct ElementaryBasis{T} <: AbstractMatrixBasis{T}
41
    iterator::ElementaryBasisIterator{T}
42

NEW
43
    function ElementaryBasis{T}(
×
44
        idim::Integer,
45
        odim::Integer,
46
    ) where {T <: AbstractMatrix{<:Number}}
NEW
47
        return new(ElementaryBasisIterator{T}(idim, odim))
×
48
    end
49
end
50

NEW
51
function ElementaryBasis{T}(dim::Integer) where {T <: AbstractMatrix{<:Number}}
×
NEW
52
    return ElementaryBasisIterator{T}(dim, dim)
×
53
end
54

55
"""
56
  - `dim`: dimensions of the matrix.
57
    Returns elementary hermitian matrices of dimension `dim` x `dim`.
58
"""
59
function hermitianbasis(T::Type{<:AbstractMatrix{<:Number}}, dim::Int)
5✔
60
    return HermitianBasisIterator{T}(dim)
6✔
61
end
62

63
hermitianbasis(dim::Int) = hermitianbasis(Matrix{ComplexF64}, dim)
3✔
64

65
function iterate(
723✔
66
    itr::HermitianBasisIterator{T},
67
    state=(1, 1),
68
) where {T <: AbstractMatrix{<:Number}}
69
    dim = itr.dim
738✔
70
    (a, b) = state
693✔
71
    a > dim && return nothing
693✔
72

73
    Tn = eltype(T)
648✔
74
    if a > b
648✔
75
        x = (im * ketbra(T, a, b, dim) - im * ketbra(T, b, a, dim)) / sqrt(Tn(2))
210✔
76
    elseif a < b
438✔
77
        x = (ketbra(T, a, b, dim) + ketbra(T, b, a, dim)) / sqrt(Tn(2))
210✔
78
    else
79
        x = ketbra(T, a, b, dim)
228✔
80
    end
81
    return x, b==dim ? (a+1, 1) : (a, b+1)
648✔
82
end
83

84
length(itr::HermitianBasisIterator) = itr.dim^2
45✔
85

86
function iterate(
17✔
87
    itr::ElementaryBasisIterator{T},
88
    state=(1, 1),
89
) where {T <: AbstractMatrix{<:Number}}
90
    idim, odim = itr.idim, itr.odim
19✔
91
    (a, b) = state
15✔
92
    a > idim && return nothing
15✔
93

94
    x = zeros(eltype(T), odim, idim)
48✔
95
    x[b, a] = one(eltype(T))
12✔
96
    return x, b == odim ? (a+1, 1) : (a, b+1)
12✔
97
end
98

99
length(itr::ElementaryBasisIterator) = itr.idim * itr.odim
×
100

101
"""
102
  - `basis`: A basis represented by a sub-type of `AbstractMatrixBasis`.
103
  - `m`: Matrix to be represented in the `basis`.
104

105
Returns a vector of coefficients of the matrix `m` in the basis `basis`.
106
"""
107
function represent(basis::T, m::AbstractMatrix{<:Number}) where {T <: AbstractMatrixBasis}
33✔
108
    return real.(tr.([m] .* basis.iterator))
33✔
109
end
110

111
function represent(
3✔
112
    basis::Type{T},
113
    m::AbstractMatrix{<:Number},
114
) where {T <: AbstractMatrixBasis}
115
    d = size(m, 1)
3✔
116
    return represent(basis{typeof(m)}(d), m)
3✔
117
end
118

119
"""
120
  - `basis`: A basis represented by a sub-type of `AbstractMatrixBasis`.
121
  - `v`: Vector of coefficients.
122

123
Returns a matrix constructed from the basis elements weighted by the coefficients in `v`.
124
"""
125
function combine(
15✔
126
    basis::AbstractMatrixBasis{T},
127
    v::Vector{<:Number},
128
) where {T <: AbstractMatrix{<:Number}}
129
    return sum(basis.iterator .* v)
15✔
130
end
131

132
"""
133
"""
134
struct ChannelBasisIterator{T} <: AbstractMatrixBasisIterator{T}
135
    idim::Int
136
    odim::Int
137
    hitr::HermitianBasisIterator{T}
138
    function ChannelBasisIterator{T}(
23✔
139
        idim::Int,
140
        odim::Int,
141
    ) where {T <: AbstractMatrix{<:Number}}
142
        return new(idim, odim, HermitianBasisIterator{T}(idim))
33✔
143
    end
144
end
145

146
abstract type AbstractChannelBasis{T} <: AbstractMatrixBasis{T} end
147
struct ChannelBasis{T} <: AbstractChannelBasis{T}
148
    iterator::ChannelBasisIterator{T}
149
    function ChannelBasis{T}(
22✔
150
        idim::Integer,
151
        odim::Integer,
152
    ) where {T <: AbstractMatrix{<:Number}}
153
        return new(ChannelBasisIterator{T}(idim, odim))
30✔
154
    end
155
end
156
"""
157
  - `T`: Type of the matrices in the basis.
158
  - `idim`: Input dimension.
159
  - `odim`: Output dimension.
160

161
Returns a basis for quantum channels.
162
"""
163
function channelbasis(T::Type{<:AbstractMatrix{<:Number}}, idim::Int, odim::Int=idim)
25✔
164
    return ChannelBasis{T}(idim, odim)
27✔
165
end
166

167
channelbasis(idim::Int, odim::Int=idim) = channelbasis(Matrix{ComplexF64}, idim, odim)
3✔
168

169
function iterate(
1,044✔
170
    itr::ChannelBasisIterator{T},
171
    state=(1, 1, 1, 1),
172
) where {T <: AbstractMatrix{<:Number}}
173
    (idim, odim) = (itr.idim, itr.odim)
1,053✔
174
    hitr = itr.hitr
1,026✔
175
    (a, c, b, d) = state
1,026✔
176
    (a == odim && c == odim && d == 2) && return nothing
1,026✔
177

178
    Tn = eltype(T)
999✔
179
    if a > c
999✔
180
        x =
360✔
181
            (
182
                ketbra(T, a, c, odim) ⊗ ketbra(T, b, d, idim) +
183
                ketbra(T, c, a, odim) ⊗ ketbra(T, d, b, idim)
184
            ) / sqrt(Tn(2))
185
    elseif a < c
639✔
186
        x =
360✔
187
            (
188
                im * ketbra(T, a, c, odim) ⊗ ketbra(T, b, d, idim) -
189
                im * ketbra(T, c, a, odim) ⊗ ketbra(T, d, b, idim)
190
            ) / sqrt(Tn(2))
191
    elseif a < odim
279✔
192
        it_res = iterate(hitr, (b, d))
252✔
193
        if isnothing(it_res)
504✔
194
            throw(ErrorException("Unexpected nothing from iterate"))
×
195
        end
196
        H = it_res[1]
252✔
197

198
        # Construct D
199
        D_vec = vcat(ones(Tn, a), Tn[-a], zeros(Tn, odim - a - 1))
288✔
200
        if T <: AbstractSparseMatrix
252✔
201
            D = spdiagm(0 => D_vec)
36✔
202
        else
203
            D = diagm(0 => D_vec)
216✔
204
        end
205

206
        x = (D ⊗ H) / sqrt(Tn(a + a^2))
252✔
207
    else
208
        if T <: AbstractSparseMatrix
27✔
209
            x = sparse(I, idim * odim, idim * odim) / sqrt(Tn(idim * odim))
9✔
210
        else
211
            x = Matrix{Tn}(I, idim * odim, idim * odim) / sqrt(Tn(idim * odim))
18✔
212
        end
213
    end
214
    if d < idim
999✔
215
        newstate = (a, c, b, d+1)
585✔
216
    elseif d == idim && b < idim
414✔
217
        newstate = (a, c, b+1, 1)
225✔
218
    elseif d == idim && b == idim && c < odim
189✔
219
        newstate = (a, c+1, 1, 1)
144✔
220
    else
221
        newstate = (a+1, 1, 1, 1)
45✔
222
    end
223
    return x, newstate
999✔
224
end
225

226
length(itr::ChannelBasisIterator) = itr.idim^2 * itr.odim^2 - itr.idim^2 + 1
30✔
227

NEW
228
function represent(
×
229
    basis::AbstractChannelBasis{T1},
230
    Φ::AbstractQuantumOperation{T2},
231
) where {T1 <: AbstractMatrix{<:Number}} where {T2 <: AbstractMatrix{<:Number}}
232
    J = convert(DynamicalMatrix{T1}, Φ)
×
NEW
233
    return represent(basis, J.matrix)
×
234
end
235

236
function combine(
9✔
237
    basis::AbstractChannelBasis{T},
238
    v::Vector{<:Number},
239
) where {T <: AbstractMatrix}
240
    m = sum(basis.iterator .* v)
15✔
241
    return DynamicalMatrix{T}(m, basis.iterator.idim, basis.iterator.odim)
9✔
242
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc