Skip to content
Draft
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.9.16"
[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
HostCPUFeatures = "3e5b6fbb-0976-4d2c-9146-d79de83f2fb0"
Expand Down Expand Up @@ -46,6 +47,7 @@ QuantumCliffordQuantikzExt = "Quantikz"
CUDA = "4.4.0, 5"
Combinatorics = "1.0"
DataStructures = "0.18"
Distributions = "0.25.116"
DocStringExtensions = "0.9"
Graphs = "1.9"
Hecke = "0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35"
Expand Down
11 changes: 11 additions & 0 deletions docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ @article{li2019measurement
doi={10.1103/PhysRevB.100.134306}
}

@article{struchalin2021experimental,
title={Experimental estimation of quantum state properties from classical shadows},
author={Struchalin, GI and Zagorovskii, Ya A and Kovlakov, EV and Straupe, SS and Kulik, SP},
journal={PRX Quantum},
volume={2},
number={1},
pages={010307},
year={2021},
publisher={APS}
}

% Canonicalization Methods

@article{garcia2012efficient,
Expand Down
138 changes: 138 additions & 0 deletions src/randoms.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Random: randperm, AbstractRNG, GLOBAL_RNG, rand!
using ILog2
import Nemo
using Distributions

##############################
# Random Paulis
Expand Down Expand Up @@ -298,3 +299,140 @@
end

random_all_to_all_clifford_circuit(nqubits::Int, ngates::Int) = random_all_to_all_clifford_circuit(GLOBAL_RNG, nqubits, ngates)

##############################
# Random stabilizer state
##############################

"""Convert an array of bits to an integer."""
function bits2int(bits)
r = 0
s = 1
for b in bits
if b & 1 != 0
r += s

Check warning on line 313 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L308-L313

Added lines #L308 - L313 were not covered by tests
end
s <<= 1
end
return r

Check warning on line 317 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L315-L317

Added lines #L315 - L317 were not covered by tests
end

"""Count the number of '1' bits in the binary representation of 'v' modulo 2."""
function parity(v)
return count_ones(v) % 2

Check warning on line 322 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L321-L322

Added lines #L321 - L322 were not covered by tests
end

"""Normalize a quantum state vector."""
function normalize_state(state)
norm_factor = norm(state)
for s in state
if s != 0
norm_factor *= s / abs(s)
break

Check warning on line 331 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L326-L331

Added lines #L326 - L331 were not covered by tests
end
end
return state / norm_factor

Check warning on line 334 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L333-L334

Added lines #L333 - L334 were not covered by tests
end

"""Find the rank of a matrix over GF(2)"""
function gf2_rank(rows)
rank = 0
while !isempty(rows)
pivot_row = pop!(rows)
if pivot_row != 0
rank += 1
lsb = pivot_row & -pivot_row
for i in eachindex(rows)
if rows[i] & lsb != 0
rows[i] ⊻= pivot_row

Check warning on line 347 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L338-L347

Added lines #L338 - L347 were not covered by tests
end
end

Check warning on line 349 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L349

Added line #L349 was not covered by tests
end
end
return rank

Check warning on line 352 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L351-L352

Added lines #L351 - L352 were not covered by tests
end

"""Multiply a matrix by a vector over GF(2)."""
function gf2_mul_mat_vec(m, v)
return bits2int([parity(m[i] & v) for i in 1:length(m)])

Check warning on line 357 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L356-L357

Added lines #L356 - L357 were not covered by tests
end

"""Calculate the dot product of two vectors over GF(2)."""
function gf2_mul_vec_vec(v1, v2)
return parity(v1 & v2)

Check warning on line 362 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L361-L362

Added lines #L361 - L362 were not covered by tests
end

"""
Computes the q-binomial coefficient, which generalizes the binomial coefficient to finite fields.

Inputs:
- n::Int: The first argument of the q-binomial coefficient.
- k::Int: The second argument of the q-binomial coefficient.
- q::Int: The base of the field (default is 2 for binary field).

Outputs:
- Int: The q-binomial coefficient C(n, k) over GF(q).
"""
function qbinomial(n, k, q = 2)
c = 1
for j in 0:(k - 1)
c *= q^n - q^j
end
for j in 0:(k - 1)
c ÷= q^k - q^j
end
return max(0, c) # Ensure non-negative values

Check warning on line 384 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L376-L384

Added lines #L376 - L384 were not covered by tests
end

"""Calculate the number of n-qubit states with 2**k nonzero elements."""
function number_of_states(n)
return [2^n * 2^((k+1)*k ÷ 2) * qbinomial(n, k) for k in 0:n]

Check warning on line 389 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L388-L389

Added lines #L388 - L389 were not covered by tests
end

"""
Generate a random n-qubit stabilizer state. It does so by using the procedure
described in the [struchalin2021experimental](@cite).

The procedure involves selecting a random value of k, sampling from the set of
stabilizer states with 2^k nonzero elements, and generating a random stabilizer
operator. The resulting state vector is normalized and returned.
"""
function random_stabilizer_state(n)
dtype = Int32
nmax = floor(Int, log2(typemax(dtype)) + 1)
if !(0 < n <= nmax)
throw(ArgumentError("Number of qubits must be in range(1, $nmax)!"))

Check warning on line 404 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L400-L404

Added lines #L400 - L404 were not covered by tests
end

dimn = 2^n
state = ComplexF32[0.0f0 for _ in 1:dimn]
weights = number_of_states(n)
dist = Distributions.Categorical(weights ./ sum(weights)) # Use a Categorical distribution for weighted sampling
k = rand(dist) - 1 # Offset by -1 to match 0-based indexing in Julia
dimk = 2^k

Check warning on line 412 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L407-L412

Added lines #L407 - L412 were not covered by tests

if k == 0
state[rand(1:dimn)] = 1.0f0
return state

Check warning on line 416 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L414-L416

Added lines #L414 - L416 were not covered by tests
end

rank = 0
R = rand(0:dimk-1, n) # Ensure R is initialized as a matrix
while rank < k
R = [rand(0:dimk-1) for _ in 1:n] # Generate `n` rows with elements in GF(2^k)
rank = gf2_rank(copy(R))
end

Check warning on line 424 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L419-L424

Added lines #L419 - L424 were not covered by tests

t = rand(0:dimn-1) # Random vector in GF(2^n)
Q = [rand(0:dimk-1) for _ in 1:k] # Generate `k` rows for Q
c = rand(0:dimk-1) # Random vector in GF(2^k)

Check warning on line 428 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L426-L428

Added lines #L426 - L428 were not covered by tests

for x in 0:(dimk - 1)
y = gf2_mul_mat_vec(R, x) ⊻ t # y = R @ x + t
ib = gf2_mul_vec_vec(c, x) # 'imaginary' bit
mb = gf2_mul_vec_vec(x, gf2_mul_mat_vec(Q, x)) # 'minus' bit
state[y + 1] = 1im^ib * (-1)^mb
end

Check warning on line 435 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L430-L435

Added lines #L430 - L435 were not covered by tests

return normalize_state(state)

Check warning on line 437 in src/randoms.jl

View check run for this annotation

Codecov / codecov/patch

src/randoms.jl#L437

Added line #L437 was not covered by tests
end
Loading