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

iitis / QuantumInformation.jl / 20929318712

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

push

github

web-flow
Support for arbitrary element types and sparse matrices (#108)

* support for arvitrary element types

* add sparse matrix support

* reformat

* more tests

* reformat

* Prepare v0.7.0 release

* Only patch version change

* update docs

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

81.82
/src/functionals.jl
1
export norm_trace,
2
    trace_distance,
3
    norm_hs,
4
    hs_distance,
5
    purity,
6
    fidelity_sqrt,
7
    fidelity,
8
    gate_fidelity,
9
    shannon_entropy,
10
    vonneumann_entropy,
11
    renyi_entropy,
12
    relative_entropy,
13
    kl_divergence,
14
    js_divergence,
15
    bures_distance,
16
    bures_angle,
17
    superfidelity,
18
    negativity,
19
    log_negativity,
20
    ppt,
21
    concurrence
22

23
using Arpack
24

25
"""
26
  - `A`: matrix.
27

28
Return [trace norm](https://www.quantiki.org/wiki/trace-norm) of matrix `A`.
29
"""
30
norm_trace(A::AbstractMatrix{<:Number}) = sum(svdvals(A))
36✔
31
function norm_trace(A::AbstractSparseMatrix{<:Number})
6✔
32
    return size(A, 1) > 32 ? sum(svds(A; nsv=min(size(A, 1) - 1, 32))[1].S) :
6✔
33
           norm_trace(Array(A))
34
end
35

36
"""
37
  - `A`: matrix.
38
  - `B`: matrix.
39

40
Return [trace distance](https://www.quantiki.org/wiki/trace-distance) between matrices `A` and `B`.
41
"""
42
function trace_distance(
9✔
43
    A::AbstractMatrix{T1},
44
    B::AbstractMatrix{T2},
45
) where {T1 <: Number, T2 <: Number}
46
    return norm_trace(A - B) / 2
9✔
47
end
48

49
"""
50
  - `A`: matrix.
51

52
Return [Hilbert–Schmidt norm](https://en.wikipedia.org/wiki/Hilbert%E2%80%93Schmidt_operator) of matrix `A`.
53
"""
54
norm_hs(A::AbstractMatrix{<:Number}) = sqrt(sum(abs2.(A)))
12✔
55

56
"""
57
  - `A`: matrix.
58
  - `B`: matrix.
59

60
Return [Hilbert–Schmidt distance](https://en.wikipedia.org/wiki/Hilbert%E2%80%93Schmidt_operator) between matrices `A` and `B`.
61
"""
62
function hs_distance(A::AbstractMatrix{<:Number}, B::AbstractMatrix{<:Number})
6✔
63
    return norm_hs(A - B)
6✔
64
end
65

66
"""
67
  - `ρ`: matrix.
68

69
Return the purity of `ρ` ∈ [1/d, 1]
70
"""
71
purity(ρ::AbstractMatrix{<:Number}) = tr(ρ^2)
6✔
72

73
"""
74
  - `ρ`: matrix.
75
  - `σ`: matrix.
76

77
Return square root of [fidelity](https://www.quantiki.org/wiki/fidelity) between matrices `ρ` and `σ`.
78
"""
79
function fidelity_sqrt(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
39✔
80
    if size(ρ, 1) != size(ρ, 2) || size(σ, 1) != size(σ, 2)
72✔
81
        throw(ArgumentError("Non square matrix"))
6✔
82
    end
83
    λ = real(eigvals(ρ * σ))
45✔
84
    return real(sum(sqrt.(λ[λ .> 0])))
33✔
85
end
86

87
function fidelity_sqrt(ρ::AbstractSparseMatrix{<:Number}, σ::AbstractSparseMatrix{<:Number})
12✔
88
    if size(ρ, 1) != size(ρ, 2) || size(σ, 1) != size(σ, 2)
21✔
89
        throw(ArgumentError("Non square matrix"))
3✔
90
    end
91
    if size(ρ, 1) > 16
9✔
92
        prod = ρ * σ
3✔
93
        λ, _ = eigs(prod; nev=size(prod, 1) - 1, which=:LM)
3✔
94
        return real(sum(sqrt.(real(λ[real(λ) .> 0]))))
3✔
95
    end
96
    return fidelity_sqrt(Array(ρ), Array(σ))
6✔
97
end
98

NEW
99
function fidelity_sqrt(ρ::AbstractSparseMatrix{<:Number}, σ::AbstractMatrix{<:Number})
×
NEW
100
    return fidelity_sqrt(Array(ρ), σ)
×
101
end
102

NEW
103
function fidelity_sqrt(ρ::AbstractMatrix{<:Number}, σ::AbstractSparseMatrix{<:Number})
×
NEW
104
    return fidelity_sqrt(ρ, Array(σ))
×
105
end
106

107
"""
108
  - `ρ`: matrix.
109
  - `σ`: matrix.
110

111
Return [fidelity](https://www.quantiki.org/wiki/fidelity) between matrices `ρ` and `σ`.
112
"""
113
function fidelity(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
15✔
114
    return fidelity_sqrt(ρ, σ)^2
15✔
115
end
116

117
fidelity(ϕ::AbstractVector{<:Number}, ψ::AbstractVector{<:Number}) = abs2(dot(ϕ, ψ))
6✔
118
fidelity(ϕ::AbstractVector{<:Number}, ρ::AbstractMatrix{<:Number}) = real(ϕ' * ρ * ϕ)
6✔
119
fidelity(ρ::AbstractMatrix{<:Number}, ϕ::AbstractVector{<:Number}) = fidelity(ϕ, ρ)
3✔
120

121
"""
122
  - `U`: quantum gate.
123
  - `V`: quantum gate.
124

125
Return [fidelity](https://www.quantiki.org/wiki/fidelity) between gates `U` and `V`.
126
"""
127
function gate_fidelity(U::AbstractMatrix{<:Number}, V::AbstractMatrix{<:Number})
15✔
128
    return abs(1.0 / size(U, 1) * tr(U'*V))
15✔
129
end
130

131
"""
132
  - `p`: vector.
133

134
Return [Shannon entorpy](https://en.wikipedia.org/wiki/Entropy_(information_theory)) of vector `p`.
135
"""
136
function shannon_entropy(p::AbstractSparseVector{<:Real})
3✔
137
    nz_p = nonzeros(p)
3✔
138
    return -sum(nz_p .* log.(nz_p))
3✔
139
end
140

141
function shannon_entropy(p::AbstractVector{<:Real})
33✔
142
    # Filter 0s for dense
143
    nz_p = p[p .> 0]
33✔
144
    return -sum(nz_p .* log.(nz_p))
33✔
145
end
146

147
"""
148
  - `x`: real number.
149

150
Return binary [Shannon entorpy](https://en.wikipedia.org/wiki/Entropy_(information_theory)) given by \$-x  \\log(x) - (1 - x)  \\log(1 - x)\$.
151
"""
152
function shannon_entropy(x::Real)
9✔
153
    return x > 0 ? -x * log(x) - (1 - x) * log(1 - x) :
9✔
154
           error("Negative number passed to shannon_entropy")
155
end
156

157
"""
158
  - `ρ`: quantum state.
159

160
Return [Von Neumann entropy](https://en.wikipedia.org/wiki/Von_Neumann_entropy) of quantum state `ρ`.
161
"""
162
function vonneumann_entropy(ρ::Hermitian{<:Number, <:AbstractSparseMatrix})
6✔
163
    n = size(ρ.data, 1)
6✔
164
    if n > 32
6✔
165
        λ, _ = eigs(ρ; nev=min(n - 1, 32), which=:LM)
3✔
166
        return shannon_entropy(real(λ[real(λ) .> 0]))
3✔
167
    end
168
    return vonneumann_entropy(Hermitian(Array(ρ.data)))
3✔
169
end
170

171
function vonneumann_entropy(ρ::Hermitian{<:Number})
27✔
172
    λ = eigvals(ρ)
27✔
173
    return shannon_entropy(λ[λ .> 0])
27✔
174
end
175

176
function vonneumann_entropy(H::AbstractMatrix{<:Number})
21✔
177
    return ishermitian(H) ? vonneumann_entropy(Hermitian(H)) :
27✔
178
           error("Non-hermitian matrix passed to entropy")
179
end
180
vonneumann_entropy(ϕ::AbstractVector{T}) where {T <: Number} = zero(T)
3✔
181

182
"""
183
  - `ρ`: quantum state.
184
  - `α`: order of Renyi entropy.
185

186
Return [Renyi entropy](https://en.wikipedia.org/wiki/R%C3%A9nyi_entropy) of quantum state `ρ`.
187
"""
188
function renyi_entropy(ρ::Hermitian{<:Number, <:AbstractSparseMatrix}, α::Real)
3✔
189
    α >= 0 && α != 1 ? () : throw(ArgumentError("Parameter α must be α ≥ 0 and α ≠ 1"))
3✔
190
    n = size(ρ.data, 1)
3✔
191
    if n > 32
3✔
192
        λ, _ = eigs(ρ; nev=min(n - 1, 32), which=:LM)
3✔
193
        λ = real(λ[real(λ) .> 0])
3✔
194
        return 1 / (1 - α) * log(sum(λ .^ α))
3✔
195
    end
NEW
196
    return renyi_entropy(Hermitian(Array(ρ.data)), α)
×
197
end
198

199
function renyi_entropy(ρ::Hermitian{<:Number}, α::Real)
12✔
200
    α >= 0 && α != 1 ? () : throw(ArgumentError("Parameter α must be α ≥ 0 and α ≠ 1"))
15✔
201
    λ = eigvals(ρ)
9✔
202
    λ = λ[λ .> 0]
9✔
203
    return 1 / (1 - α) * log(sum(λ .^ α))
9✔
204
end
205

206
renyi_entropy(ρ::AbstractMatrix{<:Number}, α::Real) = renyi_entropy(Hermitian(ρ), α)
6✔
207
"""
208
  - `ρ`: quantum state.
209
  - `σ`: quantum state.
210

211
Return [quantum relative entropy](https://en.wikipedia.org/wiki/Quantum_relative_entropy) of quantum state `ρ` with respect to `σ`.
212
"""
213
function relative_entropy(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
18✔
214
    log_σ = funcmh(log, σ)
18✔
215
    return real(-vonneumann_entropy(ρ) - tr(ρ * log_σ))
18✔
216
end
217

NEW
218
function relative_entropy(
×
219
    ρ::AbstractSparseMatrix{<:Number},
220
    σ::AbstractSparseMatrix{<:Number},
221
)
NEW
222
    if size(ρ, 1) > 16
×
NEW
223
        λ, V = eigs(σ; nev=size(σ, 1) - 1, which=:LM)
×
224
        # tr(ρ * log(σ)) = tr(ρ * V * log(D) * V') = tr(V' * ρ * V * log(D))
NEW
225
        projected_ρ = V' * ρ * V
×
NEW
226
        term2 = sum(diag(projected_ρ) .* log.(λ))
×
NEW
227
        return real(-vonneumann_entropy(ρ) - term2)
×
228
    end
NEW
229
    return relative_entropy(Array(ρ), Array(σ))
×
230
end
231

NEW
232
function relative_entropy(ρ::AbstractSparseMatrix{<:Number}, σ::AbstractMatrix{<:Number})
×
NEW
233
    return relative_entropy(Array(ρ), σ)
×
234
end
235

NEW
236
function relative_entropy(ρ::AbstractMatrix{<:Number}, σ::AbstractSparseMatrix{<:Number})
×
NEW
237
    return relative_entropy(ρ, Array(σ))
×
238
end
239

240
"""
241
  - `ρ`: quantum state.
242
  - `σ`: quantum state.
243

244
Return [Kullback–Leibler divergence](https://en.wikipedia.org/wiki/Quantum_relative_entropy) of quantum state `ρ` with respect to `σ`.
245
"""
246
function kl_divergence(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
10✔
247
    return relative_entropy(ρ, σ)
12✔
248
end
249

250
"""
251
  - `ρ`: quantum state.
252
  - `σ`: quantum state.
253

254
Return [Jensen–Shannon divergence](https://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence) of quantum state `ρ` with respect to `σ`.
255
"""
256
function js_divergence(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
3✔
257
    return 0.5kl_divergence(ρ, σ) + 0.5kl_divergence(σ, ρ)
3✔
258
end
259

260
"""
261
  - `ρ`: quantum state.
262
  - `σ`: quantum state.
263

264
Return [Bures distance](https://en.wikipedia.org/wiki/Bures_metric) between quantum states `ρ` and `σ`.
265
"""
266
function bures_distance(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
6✔
267
    return sqrt(2 - 2 * fidelity_sqrt(ρ, σ))
6✔
268
end
269

270
"""
271
  - `ρ`: quantum state.
272
  - `σ`: quantum state.
273

274
Return [Bures angle](https://en.wikipedia.org/wiki/Bures_metric) between quantum states `ρ` and `σ`.
275
"""
276
function bures_angle(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
6✔
277
    return acos(fidelity_sqrt(ρ, σ))
6✔
278
end
279

280
"""
281
  - `ρ`: quantum state.
282
  - `σ`: quantum state.
283

284
Return [superfidelity](https://www.quantiki.org/wiki/superfidelity) between quantum states `ρ` and `σ`.
285
"""
286
function superfidelity(ρ::AbstractMatrix{<:Number}, σ::AbstractMatrix{<:Number})
9✔
287
    return real(tr(ρ'*σ) + sqrt(1 - tr(ρ'*ρ)) * sqrt(1 - tr(σ'*σ)))
9✔
288
end
289

290
"""
291
  - `ρ`: quantum state.
292
  - `dims`: dimensions of subsystems.
293
  - `sys`: transposed subsystem.
294

295
Return [negativity](https://www.quantiki.org/wiki/negativity) of quantum state `ρ`.
296
"""
297
function negativity(ρ::AbstractMatrix{<:Number}, dims::Vector{Int}, sys::Int)
9✔
298
    ρ_s = ptranspose(ρ, dims, sys)
9✔
299
    λ = eigvals(ρ_s)
9✔
300
    return -real(sum(λ[λ .< 0]))
9✔
301
end
302

303
function negativity(ρ::AbstractSparseMatrix{<:Number}, dims::Vector{Int}, sys::Int)
6✔
304
    ρ_s = ptranspose(ρ, dims, sys)
6✔
305
    if size(ρ_s, 1) > 32
6✔
306
        λ, _ = eigs(ρ_s; nev=min(size(ρ_s, 1) - 1, 32), which=:SR)
3✔
307
        λ = real(λ)
3✔
308
        return -real(sum(λ[λ .< 0]))
3✔
309
    end
310
    λ = eigvals(Array(ρ_s))
4✔
311
    return -real(sum(λ[λ .< 0]))
3✔
312
end
313

314
"""
315
  - `ρ`: quantum state.
316
  - `dims`: dimensions of subsystems.
317
  - `sys`: transposed subsystem.
318

319
Return [log negativity](https://www.quantiki.org/wiki/negativity) of quantum state `ρ`.
320
"""
321
function log_negativity(ρ::AbstractMatrix{<:Number}, dims::Vector{Int}, sys::Int)
9✔
322
    ρ_s = ptranspose(ρ, dims, sys)
9✔
323
    return log(norm_trace(ρ_s))
9✔
324
end
325

326
"""
327
  - `ρ`: quantum state.
328
  - `dims`: dimensions of subsystems.
329
  - `sys`: transposed subsystem.
330

331
Return minimum eigenvalue of [positive partial transposition](https://www.quantiki.org/wiki/positive-partial-transpose) of quantum state `ρ`.
332
"""
333
function ppt(ρ::AbstractMatrix{<:Number}, dims::Vector{Int}, sys::Int)
9✔
334
    ρ_s = ptranspose(ρ, dims, sys)
9✔
335
    return minimum(eigvals(ρ_s))
9✔
336
end
337

NEW
338
function ppt(ρ::AbstractSparseMatrix{<:Number}, dims::Vector{Int}, sys::Int)
×
NEW
339
    ρ_s = ptranspose(ρ, dims, sys)
×
NEW
340
    if size(ρ_s, 1) > 16
×
NEW
341
        λ, _ = eigs(ρ_s; nev=1, which=:SR)
×
NEW
342
        return real(λ[1])
×
343
    end
NEW
344
    return minimum(eigvals(Array(ρ_s)))
×
345
end
346

347
"""
348
  - `ρ`: quantum state.
349

350
Calculates the [concurrence of a two-qubit system](https://en.wikipedia.org/wiki/Concurrence_(quantum_computing)) `ρ`.
351
"""
352
function concurrence(ρ::AbstractMatrix{<:Number})
9✔
353
    if size(ρ, 1) != 4
9✔
354
        throw(ArgumentError("Concurrence only properly defined for two qubit systems"))
3✔
355
    end
356
    σ = (sy ⊗ sy)*conj.(ρ)*(sy ⊗ sy)
12✔
357
    λ = sqrt.(sort(real(eigvals(ρ*σ)), rev=true))
6✔
358
    return max(0, λ[1]-λ[2]-λ[3]-λ[4])
6✔
359
end
360

361
function concurrence(ρ::AbstractSparseMatrix{<:Number})
362
    return concurrence(Array(ρ))
363
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