• 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

93.1
/src/channels/constructors.jl
1
export AbstractQuantumOperation,
2
    KrausOperators,
3
    SuperOperator,
4
    DynamicalMatrix,
5
    Stinespring,
6
    UnitaryChannel,
7
    IdentityChannel,
8
    POVMMeasurement,
9
    PostSelectionMeasurement
10

11
################################################################################
12
# Channels definitions and constructors
13
################################################################################
14

15
abstract type AbstractQuantumOperation{T <: AbstractMatrix{<:Number}} end
16
Base.eltype(::AbstractQuantumOperation{T}) where {T} = eltype(T)
22✔
NEW
17
Base.eltype(::Type{<:AbstractQuantumOperation{T}}) where {T} = eltype(T)
×
18

19
"""
20
  - `T`: quantum channel map.
21

22
Representation of quantum channel by Kraus operators.
23
"""
24
struct KrausOperators{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
25
    matrices::Vector{T}
26
    idim::Int
27
    odim::Int
28
    function KrausOperators{T1}(
330✔
29
        v::Vector{T2},
30
    ) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
31
        sizes = [size(k) for k in v]
440✔
32
        for s in sizes[2:end]
330✔
33
            if s!=sizes[1]
1,329✔
34
                throw(
3✔
35
                    ArgumentError(
36
                        "Kraus operators list contains matrices of different dimension",
37
                    ),
38
                )
39
            end
40
        end
663✔
41
        odim, idim = sizes[1]
327✔
42
        return new{T1}(map(T1, v), idim, odim)
327✔
43
    end
44
end
45

46
function KrausOperators{T1}(
92✔
47
    v::Vector{T2},
48
    idim::Int,
49
    odim::Int,
50
) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
51
    all((odim, idim) == size(k) for k in v) ? () :
141✔
52
    throw(ArgumentError("Matrix size and operator dimensions mismatch"))
53
    return KrausOperators{T1}(v)
135✔
54
end
55

56
length(Φ::KrausOperators) = length(Φ.matrices)
×
57

58
function orthogonalize(Φ::KrausOperators{T}) where {T <: AbstractMatrix{<:Number}}
44✔
59
    return convert(KrausOperators{T}, convert(DynamicalMatrix{T}, Φ))
66✔
60
end
61

62
"""
63
  - `T`: quantum channel map.
64

65
Representation of quantum channel by super-operator.
66
"""
67
struct SuperOperator{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
68
    matrix::T
69
    idim::Int
70
    odim::Int
71
    function SuperOperator{T1}(
102✔
72
        m::T2,
73
    ) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
74
        r, c = size(m)
153✔
75
        sr = isqrt(r)
153✔
76
        sc = isqrt(c)
153✔
77
        if r!=sr^2 || c!=sc^2
303✔
78
            throw(ArgumentError("Superoperator matrix has invalid dimensions"))
3✔
79
        end
80
        odim, idim = sr, sc
150✔
81
        return new{T1}(convert(T1, m), idim, odim)
150✔
82
    end
83
end
84

85
function SuperOperator{T1}(
102✔
86
    m::T2,
87
    idim::Int,
88
    odim::Int,
89
) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
90
    (odim^2, idim^2) == size(m) ? () :
156✔
91
    throw(ArgumentError("Matrix size and operator dimensions mismatch"))
92
    return SuperOperator{T1}(m)
150✔
93
end
94

95
"""
96
  - `channel`: quantum channel map.
97
  - `idim`: square root of the [super-operator](https://en.wikipedia.org/wiki/Superoperator) matrix input dimension.
98
  - `odim`: square root of the [super-operator](https://en.wikipedia.org/wiki/Superoperator) matrix output dimension.
99

100
Transforms quntum channel into super-operator matrix.
101
"""
102
function SuperOperator{T}(
6✔
103
    channel::Function,
104
    idim::Int,
105
    odim::Int,
106
) where {T <: AbstractMatrix{<:Number}}
107
    odim > 0 && idim > 0 ? () :
9✔
108
    throw(ArgumentError("Channel dimensions have to be nonnegative"))
109

110
    m = zeros(eltype(T), idim^2, odim^2)
48✔
111
    for (i, e) in enumerate(ElementaryBasisIterator{Matrix{Int}}(idim, odim))
6✔
112
        m[:, i] = res(channel(e))
12✔
113
    end
21✔
114
    return SuperOperator(m, idim, odim)
3✔
115
end
116

117
"""
118
  - `T`: quantum channel map.
119

120
Representation of quantum channel by Dynamical matrix operators.
121
"""
122
struct DynamicalMatrix{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
123
    matrix::T
124
    idim::Int
125
    odim::Int
126
    function DynamicalMatrix{T1}(m, idim, odim) where {T1 <: AbstractMatrix{<:Number}}
183✔
127
        r, c = size(m)
270✔
128
        if r!=c || r!=idim*odim
534✔
129
            throw(ArgumentError("DynamicalMatrix matrix has invalid dimensions"))
6✔
130
        end
131
        return new(convert(T1, m), idim, odim)
264✔
132
    end
133
end
134

135
"""
136
  - `T`: quantum channel map.
137

138
Stinespring representation of quantum channel.
139
"""
140
struct Stinespring{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
141
    matrix::T
142
    idim::Int
143
    odim::Int
144
    function Stinespring{T1}(m, idim, odim) where {T1 <: AbstractMatrix{<:Number}}
46✔
145
        r, c = size(m)
69✔
146
        if r!=idim * (odim^2) || c!=idim
135✔
147
            throw(ArgumentError("Stinespring matrix has invalid dimensions"))
3✔
148
        end
149
        return new(T1(m), idim, odim)
66✔
150
    end
151
end
152

153
"""
154
  - `T`: quantum channel map.
155

156
Representation of unitary channel.
157
"""
158
struct UnitaryChannel{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
159
    matrix::T
160
    idim::Int
161
    odim::Int
162
    function UnitaryChannel{T1}(
68✔
163
        m::T2,
164
    ) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
165
        odim, idim = size(m)
102✔
166
        idim == odim ? () : throw(ArgumentError("UnitaryChannel matrix has to be square"))
105✔
167
        return new{T1}(convert(T1, m), idim, odim)
99✔
168
    end
169
end
170

171
function UnitaryChannel{T1}(
18✔
172
    m::T2,
173
    idim::Int,
174
    odim::Int,
175
) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
176
    (odim, idim) == size(m) ? () :
30✔
177
    throw(ArgumentError("Matrix size and operator dimensions mismatch"))
178
    return UnitaryChannel{T1}(convert(T1, m))
24✔
179
end
180

181
"""
182
  - `T`: quantum channel map.
183

184
Representation of identity channel.
185
"""
186
struct IdentityChannel{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
187
    idim::Int
188
    odim::Int
189
    function IdentityChannel{T}(dim::Int) where {T <: AbstractMatrix{<:Number}}
8✔
190
        return new{T}(dim, dim)
12✔
191
    end
192
end
193

NEW
194
function IdentityChannel(::Type{T}, dim::Int) where {T <: AbstractMatrix{<:Number}}
×
NEW
195
    return IdentityChannel{T}(dim)
×
196
end
197
IdentityChannel(dim::Int) = IdentityChannel{Matrix{ComplexF64}}(dim)
12✔
198

199
################################################################################
200
# measurements
201
################################################################################
202
struct POVMMeasurement{T <: AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T}
203
    matrices::Vector{T}
204
    idim::Int
205
    odim::Int
206
    function POVMMeasurement{T1}(
27✔
207
        v::Vector{T2},
208
    ) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
209
        sizes = [size(p) for p in v]
36✔
210
        for s in sizes[2:end]
27✔
211
            if s!=sizes[1]
84✔
212
                throw(
3✔
213
                    ArgumentError(
214
                        "POVM operators list contains matrices of different dimension",
215
                    ),
216
                )
217
            end
218
        end
39✔
219
        idim = size(v[1], 1)
24✔
220
        odim = length(v)
24✔
221

222
        return new{T1}(map(T1, v), idim, odim)
24✔
223
    end
224
end
225

226
function POVMMeasurement{T1}(
6✔
227
    v::Vector{T2},
228
    idim::Int,
229
    odim::Int,
230
) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
231
    all((idim, idim) == size(p) for p in v) ? () :
9✔
232
    throw(
233
        ArgumentError(
234
            "POVMs must be square matrices of size equal to operator inupt dimension",
235
        ),
236
    )
237
    odim == length(v) ? () :
6✔
238
    throw(ArgumentError("Operator output dimension must match number of POVM operators"))
NEW
239
    return POVMMeasurement{T1}(v)
×
240
end
241

242
struct PostSelectionMeasurement{T <: AbstractMatrix{<:Number}} <:
243
       AbstractQuantumOperation{T}
244
    matrix::T
245
    idim::Int
246
    odim::Int
247
    function PostSelectionMeasurement{T1}(
4✔
248
        m::T2,
249
    ) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
250
        odim, idim = size(m)
6✔
251
        return new{T1}(convert(T1, m), idim, odim)
6✔
252
    end
253
end
254

255
function PostSelectionMeasurement{T1}(
3✔
256
    m::T2,
257
    idim::Int,
258
    odim::Int,
259
) where {T1 <: AbstractMatrix{<:Number}, T2 <: AbstractMatrix{<:Number}}
260
    odim,
3✔
261
    idim == size(m) ? () :
262
    throw(ArgumentError("Matrix size and operator dimensions mismatch"))
NEW
263
    return PostSelectionMeasurement{T1}(m)
×
264
end
265

266
################################################################################
267
# typeless constructors
268
################################################################################
269
for qop in (:SuperOperator, :UnitaryChannel, :PostSelectionMeasurement)
270
    @eval begin
271
        function $qop(m::T) where {T <: AbstractMatrix{<:Number}}
84✔
272
            return $qop{T}(m)
87✔
273
        end
274

275
        function $qop(m::T, idim::Int, odim::Int) where {T <: AbstractMatrix{<:Number}}
19✔
276
            return $qop{T}(m, idim, odim)
24✔
277
        end
278
    end
279
end
280

281
function SuperOperator(channel::Function, idim::Int, odim::Int)
3✔
282
    return SuperOperator{Matrix{ComplexF64}}(channel, idim, odim)
3✔
283
end
284

285
for qop in (:DynamicalMatrix, :Stinespring)
286
    @eval begin
287
        function $qop(m::T, idim::Int, odim::Int) where {T <: AbstractMatrix{<:Number}}
39✔
288
            return $qop{T}(m, idim, odim)
39✔
289
        end
290
    end
291
end
292

293
for qop in (:KrausOperators, :POVMMeasurement)
294
    @eval begin
295
        function $qop(v::T) where {T <: Vector{M}} where {M <: AbstractMatrix{<:Number}}
211✔
296
            return $qop{M}(v)
213✔
297
        end
298

299
        function $qop(
9✔
300
            v::T,
301
            idim::Int,
302
            odim::Int,
303
        ) where {T <: Vector{M}} where {M <: AbstractMatrix{<:Number}}
304
            return $qop{M}(v, idim, odim)
9✔
305
        end
306
    end
307
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