Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions src/project_trace_reset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,129 @@
d, anticommutes, result
end

"""
A faster special-case version of [`project!`](@ref) for sparse PauliOperators.

This function is faster when the PauliOperator is sparse, i.e. it has only a small number of (not identity) elements, compared to the number of system qubits. Especially when the measured qubits are close to each other.

For single qubit measurements, use [`projectX!`](@ref), [`projectY!`](@ref), or [`projectZ!`](@ref), since they are faster.

See also: [`project!`](@ref), [`projectX!`](@ref), [`projectY!`](@ref), [`projectZ!`](@ref).
"""
function project_sparse!(state,qubits::Vector{<:Integer}, local_pauli::PauliOperator;keep_result::Bool=true,phases::Bool=true)
@valbooldispatch _project_sparse!(state,qubits,local_pauli;keep_result=Val(keep_result),phases=Val(phases)) keep_result phases

Check warning on line 451 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L450-L451

Added lines #L450 - L451 were not covered by tests
end
function _project_sparse!(d::MixedDestabilizer,qubits::Vector{<:Integer},local_pauli::PauliOperator;keep_result::Val{Bkr}=Val(true),phases::Val{Bp}=Val(true)) where {Bkr, Bp}
anticommutes = 0
tab = QuantumClifford.tab(d)
stabilizer = stabilizerview(d)
destabilizer = destabilizerview(d)
r = d.rank
n = nqubits(d)

Check warning on line 459 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L453-L459

Added lines #L453 - L459 were not covered by tests
# The idea is to still do the comm xor between UInt64s because obeying to the memory layout is faster then checking individual bits.
packed_indices = _packed_indices(d,qubits) # TODO: find a way to to this without (or with minimal) allocations

Check warning on line 461 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L461

Added line #L461 was not covered by tests
# Check whether we anticommute with any of the stabilizer rows
for i in 1:r
if comm(stabilizer, i, packed_indices, local_pauli)!=0x0
anticommutes = i
break

Check warning on line 466 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L463-L466

Added lines #L463 - L466 were not covered by tests
end
end
if anticommutes == 0
anticomlog = 0

Check warning on line 470 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L468-L470

Added lines #L468 - L470 were not covered by tests

for i in r+1:n
if comm(stabilizer, i, packed_indices, local_pauli)!=0x0
anticomlog = i
break

Check warning on line 475 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L472-L475

Added lines #L472 - L475 were not covered by tests
end
end
if anticomlog == 0
for i in n+r+1:2n
if comm(stabilizer, i, packed_indices, local_pauli)!=0x0
anticomlog = i
break

Check warning on line 482 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L477-L482

Added lines #L477 - L482 were not covered by tests
end
end

Check warning on line 484 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L484

Added line #L484 was not covered by tests
end
if anticomlog!=0
if anticomlog<=n
rowswap!(tab, r+1+n, anticomlog)
n!=r+1 && anticomlog!=r+1 && rowswap!(tab, r+1, anticomlog+n)

Check warning on line 489 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L486-L489

Added lines #L486 - L489 were not covered by tests
else
rowswap!(tab, r+1, anticomlog-n)
rowswap!(tab, r+1+n, anticomlog)

Check warning on line 492 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L491-L492

Added lines #L491 - L492 were not covered by tests
end
anticomm_update_rows(tab,packed_indices,r+1,n,r+1,local_pauli,phases)
d.rank+=1
anticommutes = d.rank
tab[r+1] = tab[n+r+1]

Check warning on line 497 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L494-L497

Added lines #L494 - L497 were not covered by tests
# replace row
zero!(tab, n+r+1)
@inbounds for (i, col) in enumerate(qubits)
tab[n+r+1, col] = local_pauli[i]
end
result = nothing

Check warning on line 503 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L499-L503

Added lines #L499 - L503 were not covered by tests
else
if Bkr
new_pauli = zero(PauliOperator, n)
for i in 1:r
comm(stabilizer, i, packed_indices, local_pauli)!=0x0 && mul_left!(new_pauli, stabilizer, i, phases=phases)
end
result = new_pauli.phase[]

Check warning on line 510 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L505-L510

Added lines #L505 - L510 were not covered by tests
else
result = nothing

Check warning on line 512 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L512

Added line #L512 was not covered by tests
end
end
else
anticomm_update_rows(tab,packed_indices,r,n,anticommutes,local_pauli,phases)
destabilizer[anticommutes] = stabilizer[anticommutes]
zero!(stabilizer, anticommutes)
@inbounds for (i, col) in enumerate(qubits)
stabilizer[anticommutes, col] = local_pauli[i]
end
result = nothing

Check warning on line 522 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L516-L522

Added lines #L516 - L522 were not covered by tests
end
d, anticommutes, result

Check warning on line 524 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L524

Added line #L524 was not covered by tests
end
# find the column indices of the UInt64 integers that the qubits are packed into in the tableau. There is probably a better way to do this. Pre allocation is hard, because two qubits can be packed into the same UInt64 integer (which would be good).
@inline function _packed_indices(d::MixedDestabilizer,qubits::Vector{<:Integer})
type_size = sizeof(eltype(tab(d).xzs)) * 8
n = nqubits(d)
packed_indices_x = unique(div.(qubits.-1,type_size).+1)
packed_indices_z = packed_indices_x.+(div(n-1,type_size)+1)
vcat(packed_indices_x, packed_indices_z)

Check warning on line 532 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L527-L532

Added lines #L527 - L532 were not covered by tests
end
@inline function anticomm_update_rows(tab,cols,r,n,anticommutes,local_pauli::PauliOperator,phases::Val{B}=Val(true)) where {B}
for i in r+1:n
if comm(tab, i, cols, local_pauli)!=0x0
mul_left!(tab, i, n+anticommutes; phases=phases)

Check warning on line 537 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L534-L537

Added lines #L534 - L537 were not covered by tests
end
end
for i in n+anticommutes+1:2n
if comm(tab, i, cols, local_pauli)!=0x0
mul_left!(tab, i, n+anticommutes; phases=phases)

Check warning on line 542 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L539-L542

Added lines #L539 - L542 were not covered by tests
end
end
for i in 1:r
if i!=anticommutes && comm(tab, i, cols, local_pauli)!=0x0
mul_left!(tab, i, n+anticommutes; phases=Val(false))

Check warning on line 547 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L544-L547

Added lines #L544 - L547 were not covered by tests
end
end

Check warning on line 549 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L549

Added line #L549 was not covered by tests
end

# TODO: move this into QuantumClifford.jl (file)
@inline function comm(stab::Stabilizer,row,cols::Vector{<:Integer},local_pauli::PauliOperator)

Check warning on line 553 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L553

Added line #L553 was not covered by tests
# Check whether the row anticommutes with the local Pauli operator
# (which is a length(cols) qubit Pauli operator)
comm(local_pauli.xz, (@view tab(stab).xzs[cols,row]))

Check warning on line 556 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L556

Added line #L556 was not covered by tests
end
@inline function comm(tab::Tableau,row,cols::Vector{<:Integer},local_pauli::PauliOperator)

Check warning on line 558 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L558

Added line #L558 was not covered by tests
# Check whether the row anticommutes with the local Pauli operator
# (which is a length(cols) qubit Pauli operator)
comm(local_pauli.xz, (@view tab.xzs[cols,row]))

Check warning on line 561 in src/project_trace_reset.jl

View check run for this annotation

Codecov / codecov/patch

src/project_trace_reset.jl#L561

Added line #L561 was not covered by tests
end

"""
Measure a given qubit in the X basis.
A faster special-case version of [`project!`](@ref).
Expand Down
Loading