Open
Description
Environment
qiskit 1.3.1
python 3.13.1
Ubuntu 20.04.6
What is happening?
The distribution of Cliffords produced by the quantum_info.random_clifford() function is not uniform
How can we reproduce the issue?
import numpy as np
from scipy.stats import chisquare
import stim ###required to canonicalise tableaus
#Count number of n qubit stabilizers
num_qubits_stab_test=2
iter_count_stabstate = [(2**(num_qubits_stab_test-k)) + 1 for k in range(0,num_qubits_stab_test)]
print("num_stabilizers = ",(2**num_qubits_stab_test)*np.prod(iter_count_stabstate))
#generate 10000 random cliffords, use stim to reduce to a unique canonical form for each stabilizer state and store each unique clifford tableau found on produced_cliffs
produced_cliffs = []
for n in range(10000):
rand_cliff = random_clifford(num_qubits_stab_test)
reduced_stab_matrix=[list(str(x).replace("_","I"))[1:] + [-1 if y=="-" else 1 for y in list(str(x))[0]] for x in stim.Tableau.from_stabilizers([stim.PauliString(x) for x in rand_cliff.to_labels(mode="S")]).to_stabilizers(canonicalize=True)]
in_produced_cliffs = [np.array_equal(np.array(reduced_stab_matrix),x) for x in produced_cliffs]
if True not in in_produced_cliffs:
produced_cliffs.append(np.array(reduced_stab_matrix))
print(len(produced_cliffs))
#check we found all cliffords
assert(len(produced_cliffs) == (2**num_qubits_stab_test)*np.prod(iter_count_stabstate))
#generate set of samples from random_clifford and reduce to canonical form with stim and store
all_produced_cliffs = []
for n in range(400000):
rand_cliff = random_clifford(num_qubits_stab_test,seed=np.random.randint(1e12))
reduced_stab_matrix=[list(str(x).replace("_","I"))[1:] + [-1 if y=="-" else 1 for y in list(str(x))[0]] for x in stim.Tableau.from_stabilizers([stim.PauliString(x) for x in rand_cliff.to_labels(mode="S")]).to_stabilizers(canonicalize=True)]
all_produced_cliffs.append(np.array(reduced_stab_matrix))
#count number of samples generated for each unique clifford, also split into two sets of samples for comparative bar plot
stab_counts= [0]*len(produced_cliffs)
stab_counts1= [0]*len(produced_cliffs)
stab_counts2= [0]*len(produced_cliffs)
for m in range(len(all_produced_cliffs)):
for n in range(len(produced_cliffs)):
if np.array_equal(produced_cliffs[n],all_produced_cliffs[m]):
stab_counts[n]+=1
###split into two seperate sets of counts for comparison
if m<len(all_produced_cliffs)//2:
stab_counts1[n]+=1
else:
stab_counts2[n]+=1
break
print("counts of stabilizers produced: ",stab_counts)
#perform chi square test for uniform randomness
# Example: Observed frequencies from a histogram (e.g., dice rolls)
observed_counts = stab_counts
# Expected frequencies assuming uniformity
expected_counts = np.array([(sum(observed_counts)/len(stab_counts))]*len(stab_counts))
# Perform chi-square test
chi_stat, p_value = chisquare(observed_counts, expected_counts)
# Print results
print(f"Chi-Square Statistic: {chi_stat:.8f}")
print(f"P-Value: {p_value:.8f}")
# Interpretation
alpha = 0.05 # Significance level
if p_value < alpha:
print("Reject the null hypothesis: The data is NOT uniformly random.")
else:
print("Fail to reject the null hypothesis: The data is consistent with uniform randomness.")
#optionally plot bar chart for independent set of samples
# import matplotlib.pyplot as plt
# X_axis = np.arange(len(stab_counts1))
# plt.bar(X_axis-0.2,stab_counts1,0.4,alpha=1.)
# plt.bar(X_axis+0.2,stab_counts2,0.4,alpha=1.) ```
### What should happen?
The distribution produced should pass the chi-squared test for uniform randomness, for an example of expected behaviour the random Clifford generation can be performed with stim:
``` rand_cliff = stim.Tableau.random(num_qubits_stab_test)
reduced_stab_matrix=[list(str(x).replace("_","I"))[1:] + [-1 if y=="-" else 1 for y in list(str(x))[0]] for x in rand_cliff.to_stabilizers(canonicalize=True)]
Any suggestions?
potentially related bug report: #13590
Activity