Skip to content

Commit 86d5c0a

Browse files
committed
adding codereview suggestions
1 parent b616cdd commit 86d5c0a

File tree

3 files changed

+65
-90
lines changed

3 files changed

+65
-90
lines changed

docs/src/references.bib

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,13 @@ @article{gullans2020dynamical
111111
publisher={APS}
112112
}
113113

114-
@incollection{hein2006entanglement,
114+
@article{hein2006entanglement,
115115
title={Entanglement in graph states and its applications},
116-
author={Hein, Marc and D{\"u}r, Wolfgang and Eisert, Jens and Raussendorf, Robert and Van den Nest, Maarten and Briegel, H-J},
117-
booktitle={Quantum computers, algorithms and chaos},
118-
pages={115--218},
119-
year={2006},
120-
publisher={IOS Press}
116+
author={Hein, Marc and D{\"u}r, Wolfgang and Eisert, Jens and Raussendorf, Robert and Nest, M and Briegel, H-J},
117+
journal={arXiv preprint quant-ph/0602096},
118+
url={https://arxiv.org/abs/quant-ph/0602096},
119+
doi={10.48550/arXiv.quant-ph/0602096},
120+
year={2006}
121121
}
122122

123123
@article{wilde2009logical,

src/entanglement.jl

Lines changed: 49 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ The bigram set `B(𝒢)` encodes these endpoints as pairs:
144144
`B(𝒢) ≡ {(𝓁(g₁),𝓇(g₁)),…,(𝓁(gₙ),𝓇(gₙ))}`
145145
146146
The clipped gauge `𝒢` is a specific choice of stabilizer state where exactly two stabilizer endpoints exist at each site,
147-
ensuring `ρ𝓁(x) + ρ𝓇(x) = 2` for all sites `x`.
147+
ensuring `ρₗ(x) + ρᵣ(x) = 2` for all sites `x` where `ρ` represents the reduced density matrix for the subsystem under
148+
consideration.
148149
149150
In the clipped gauge, entanglement entropy is determined only by the stabilizers' endpoints, regardless of their internal structure.
150151
@@ -187,26 +188,12 @@ end
187188
"""
188189
$TYPEDSIGNATURES
189190
190-
Get bipartite entanglement entropy of a subsystem `𝒶`.
191+
Get bipartite entanglement entropy of a subsystem
191192
192-
In a system of `n`-qubits divided into regions `𝒶` and `𝒷`, the Rényi (or von Neumann)
193-
entropy `S(ρ𝒶)` where `ρ𝒶` is reduced density matrix, quantifies the quantum information
194-
in region `𝒶` after tracing out region `𝒷`.
193+
Defined as entropy of the reduced density matrix.
195194
196-
The entropy is given by: `S(ρ𝒶) = |𝒶| - log₂ |𝒢𝒶|`, where `𝒢𝒶` is a subgroup of stabilizers
197-
acting non-trivially on `𝒶`. This entropy measures the number of independent stabilizers
198-
on `𝒶`, reflecting the quantum correlations between regions.
199-
200-
The stabilizer group `𝒢`, viewed as a binary vector space `V`, can be decomposed such that:
201-
`S𝒶 = |𝒷| - dim V𝒷 = dim (Π𝒶 V) - |𝒶|` where `Π𝒶` and `Π𝒷` are truncation maps for regions
202-
`𝒶` and `𝒷`, respectively.
203-
204-
Initially, each site has one stabilizer and zero entanglement, but as stabilizers enter
205-
region `𝒶` over time, entanglement `S𝒶` increases by one bit for each new independent
206-
operator in `𝒶`.
207-
208-
It can be calculated with multiple different algorithms, the most performant one depending
209-
on the particular case.
195+
It can be calculated with multiple different algorithms,
196+
the most performant one depending on the particular case.
210197
211198
Currently implemented are the `:clip` (clipped gauge), `:graph` (graph state), and `:rref` (Gaussian elimination) algorithms.
212199
Benchmark your particular case to choose the best one.
@@ -224,13 +211,24 @@ Get bipartite entanglement entropy of a contiguous subsystem by passing through
224211
If `clip=false` is set the canonicalization step is skipped, useful if the input state is already in the clipped gauge.
225212
226213
```jldoctest
214+
julia> using Graphs # hide
215+
227216
julia> s = ghz(3)
228217
+ XXX
229218
+ ZZ_
230219
+ _ZZ
231220
232221
julia> entanglement_entropy(s, 1:3, Val(:clip))
233222
0
223+
224+
julia> s = Stabilizer(Graph(ghz(4)))
225+
+ XZZZ
226+
+ ZX__
227+
+ Z_X_
228+
+ Z__X
229+
230+
julia> entanglement_entropy(s, [1,4], Val(:graph))
231+
1
234232
```
235233
236234
See also: [`bigram`](@ref), [`canonicalize_clip!`](@ref)
@@ -250,19 +248,6 @@ $TYPEDSIGNATURES
250248
251249
Get bipartite entanglement entropy by first converting the state to a graph and computing the rank of the adjacency matrix.
252250
253-
```jldoctest
254-
julia> using Graphs # hide
255-
256-
julia> s = Stabilizer(Graph(ghz(4)))
257-
+ XZZZ
258-
+ ZX__
259-
+ Z_X_
260-
+ Z__X
261-
262-
julia> entanglement_entropy(s, [1,4], Val(:graph))
263-
1
264-
```
265-
266251
Based on "Entanglement in graph states and its applications".
267252
""" # TODO you should use [hein2006entanglement](@cite) instead of "Entanglement in graph states and its applications", but Documenter is giving the weirdest error if you do so...
268253
function entanglement_entropy(state::AbstractStabilizer, subsystem::AbstractVector, algorithm::Val{:graph})
@@ -281,20 +266,7 @@ Get bipartite entanglement entropy by converting to RREF form (i.e., partial tra
281266
282267
The state will be partially canonicalized in an RREF form.
283268
284-
```jldoctest
285-
julia> s = MixedDestabilizer(T"-IX -YX -ZZ -ZI",2)
286-
𝒟ℯ𝓈𝓉𝒶𝒷
287-
- _X
288-
- YX
289-
𝒮𝓉𝒶𝒷
290-
- ZZ
291-
- Z_
292-
293-
julia> entanglement_entropy(s, [1,2], Val(:rref))
294-
0
295-
```
296-
297-
See also: [`canonicalize_rref!`](@ref), [`traceout!`](@ref).
269+
See also: [`canonicalize_rref!`](@ref), [`traceout!`](@ref), [`mutual_information`](@ref)
298270
"""
299271
function entanglement_entropy(state::AbstractStabilizer, subsystem::AbstractVector, algorithm::Val{:rref}; pure::Bool=false)
300272
nb_of_qubits = nqubits(state)
@@ -310,39 +282,20 @@ function entanglement_entropy(state::AbstractStabilizer, subsystem::AbstractVect
310282
return nb_of_qubits - rank_after_deletion - nb_of_deletions
311283
end
312284

313-
"""
314-
$TYPEDSIGNATURES
315-
"""
316285
entanglement_entropy(state::MixedDestabilizer, subsystem::AbstractVector, a::Val{:rref}) = entanglement_entropy(state, subsystem, a; pure=nqubits(state)==rank(state))
317286

318287
_to_unitrange(x) = isa(x, UnitRange) ? x : isa(x, AbstractVector) && !isempty(x) && all(diff(x) .== 1) ? UnitRange(first(x), last(x)) : error("Cannot convert to UnitRange: $x")
319288

320289
"""
321290
$TYPEDSIGNATURES
322291
323-
The mutual information between subsystems `𝒶` and `𝒷` in a stabilizer state is
324-
given by `Iⁿ(𝒶, 𝒷) = Sⁿ𝒶 + Sⁿ𝒷 - Sⁿ𝒶𝒷`, where the Rényi index `n` is dropped because, for
325-
Clifford circuits, all Renyi entropies are equal due to the flat entanglement spectrum.
292+
The mutual information between subsystems `𝒶` and `𝒷` in a stabilizer state is given by `I(𝒶, 𝒷) = S𝒶 + S𝒷 - S𝒶𝒷`.
326293
327294
```jldoctest
295+
julia> using Graphs # hide
296+
328297
julia> mutual_information(ghz(3), 1:2, 3:4, Val(:clip))
329298
2
330-
```
331-
332-
See Eq. E6 of [li2019measurement](@cite).
333-
"""
334-
function mutual_information(state::AbstractStabilizer, A::UnitRange, B::UnitRange, algorithm::Val{:clip}; clip::Bool=true)
335-
S𝒶 = entanglement_entropy(state, A, algorithm; clip=clip)
336-
S𝒷 = entanglement_entropy(state, B, algorithm; clip=clip)
337-
S𝒶𝒷 = entanglement_entropy(state, _to_unitrange(union(A, B)), algorithm; clip=clip)
338-
return S𝒶 + S𝒷 - S𝒶𝒷
339-
end
340-
341-
"""
342-
$TYPEDSIGNATURES
343-
344-
```jldoctest
345-
julia> using Graphs # hide
346299
347300
julia> s = Stabilizer(Graph(ghz(4)))
348301
+ XZZZ
@@ -354,17 +307,34 @@ julia> mutual_information(s, [1,2], [3, 4], Val(:graph))
354307
2
355308
```
356309
310+
See Eq. E6 of [li2019measurement](@cite). See also: [`entanglement_entropy`](@ref)
357311
"""
358-
function mutual_information(state::AbstractStabilizer, A::AbstractVector, B::AbstractVector, algorithm::Union{Val{:rref}, Val{:graph}}; pure::Bool=false)
359-
if algorithm == Val(:graph)
360-
S𝒶 = entanglement_entropy(state, A, algorithm)
361-
S𝒷 = entanglement_entropy(state, B, algorithm)
362-
S𝒶𝒷 = entanglement_entropy(state, union(A, B), algorithm)
363-
return S𝒶 + S𝒷 - S𝒶𝒷
364-
else
365-
S𝒶 = entanglement_entropy(state, A, algorithm; pure=pure)
366-
S𝒷 = entanglement_entropy(state, B, algorithm; pure=pure)
367-
S𝒶𝒷 = entanglement_entropy(state, union(A, B), algorithm; pure=pure)
368-
return S𝒶 + S𝒷 - S𝒶𝒷
312+
function mutual_information(state::AbstractStabilizer, A::UnitRange, B::UnitRange, algorithm::Val{:clip}; clip::Bool=true)
313+
if !isempty(intersect(A, B))
314+
throw(ArgumentError("Ranges A and B must not overlap."))
315+
end
316+
S𝒶 = entanglement_entropy(state, A, algorithm; clip=clip)
317+
S𝒷 = entanglement_entropy(state, B, algorithm; clip=clip)
318+
S𝒶𝒷 = entanglement_entropy(state, _to_unitrange(union(A, B)), algorithm; clip=clip)
319+
return S𝒶 + S𝒷 - S𝒶𝒷
320+
end
321+
322+
function mutual_information(state::AbstractStabilizer, A::AbstractVector, B::AbstractVector, algorithm::Val{:rref}; pure::Bool=false)
323+
if !isempty(intersect(A, B))
324+
throw(ArgumentError("Ranges A and B must not overlap."))
325+
end
326+
S𝒶 = entanglement_entropy(state, A, algorithm; pure=pure)
327+
S𝒷 = entanglement_entropy(state, B, algorithm; pure=pure)
328+
S𝒶𝒷 = entanglement_entropy(state, union(A, B), algorithm; pure=pure)
329+
return S𝒶 + S𝒷 - S𝒶𝒷
330+
end
331+
332+
function mutual_information(state::AbstractStabilizer, A::AbstractVector, B::AbstractVector, algorithm::Val{:graph})
333+
if !isempty(intersect(A, B))
334+
throw(ArgumentError("Ranges A and B must not overlap."))
369335
end
336+
S𝒶 = entanglement_entropy(state, A, algorithm)
337+
S𝒷 = entanglement_entropy(state, B, algorithm)
338+
S𝒶𝒷 = entanglement_entropy(state, union(A, B), algorithm)
339+
return S𝒶 + S𝒷 - S𝒶𝒷
370340
end

test/test_entanglement.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
@test entanglement_entropy(copy(s), subsystem, Val(:graph))==2
5151
@test entanglement_entropy(copy(s), subsystem, Val(:rref))==2
5252
end
53-
53+
5454
@testset "Mutual Information for Clifford Circuits" begin
5555
for n in test_sizes
5656
s = random_stabilizer(n)
@@ -59,10 +59,15 @@
5959
startB = rand(subsystem_rangeA)
6060
endB = rand(startB:n)
6161
subsystem_rangeB = startB:endB
62-
@test mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:clip)) == mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:rref)) == mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:graph))
63-
# The mutual information `Iⁿ(𝒶, 𝒷) = Sⁿ𝒶 + Sⁿ𝒷 - Sⁿ𝒶𝒷 for Clifford circuits is non-negative since n is 1 [li2019measurement](@cite).
64-
@test mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:clip)) & mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:rref)) >= 0
65-
@test mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:graph)) >= 0
62+
if !isempty(intersect(subsystem_rangeA, subsystem_rangeB))
63+
@test_throws ArgumentError mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:clip))
64+
@test_throws ArgumentError mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:rref))
65+
@test_throws ArgumentError mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:graph))
66+
else
67+
@test mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:clip)) == mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:rref)) == mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:graph))
68+
# The mutual information `I(𝒶, 𝒷) = S𝒶 + S𝒷 - S𝒶𝒷 for Clifford circuits is non-negative [li2019measurement](@cite).
69+
@test mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:clip)) & mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:rref)) & mutual_information(copy(s), subsystem_rangeA, subsystem_rangeB, Val(:graph)) >= 0
70+
end
6671
end
6772
end
6873
end

0 commit comments

Comments
 (0)