Skip to content

Commit 0d4ee23

Browse files
Fix random_clifford (Qiskit#13606)
* fix and tests * Using a fixed rather than random clifford in one of the tests * reno * restoring previous docstring that was changed accidentally * updating in-code comment * also checking decompositions for random 3q cliffords
1 parent cc932b8 commit 0d4ee23

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

crates/accelerate/src/synthesis/clifford/random_clifford.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,15 @@ pub fn random_clifford_tableau_inner(num_qubits: usize, seed: Option<u64>) -> Ar
125125

126126
// Compute the full stabilizer tableau
127127

128-
// The code below is identical to the Python implementation, but is based on the original
129-
// code in the paper.
130-
128+
// The code below is based on the original code in the referenced paper.
131129
let mut table = Array2::from_elem((2 * num_qubits, 2 * num_qubits), false);
132130

133131
// Apply qubit permutation
134132
for i in 0..num_qubits {
135-
replace_row_inner(table.view_mut(), i, table2.slice(s![i, ..]));
133+
replace_row_inner(table.view_mut(), i, table2.slice(s![perm[i], ..]));
136134
replace_row_inner(
137135
table.view_mut(),
138-
perm[i] + num_qubits,
136+
i + num_qubits,
139137
table2.slice(s![perm[i] + num_qubits, ..]),
140138
);
141139
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
Fixed a bug in :func:`~qiskit.quantum_info.random_clifford` that stopped it
5+
from sampling the full Clifford group.

test/python/quantum_info/operators/symplectic/test_clifford.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,12 @@ def test_from_circuit_with_all_types(self):
473473
# and even circuits with other clifford objects.
474474
linear_function = LinearFunction([[0, 1], [1, 1]])
475475
pauli_gate = PauliGate("YZ")
476-
cliff = random_clifford(2, seed=777)
476+
477+
qc_cliff = QuantumCircuit(2)
478+
qc_cliff.h(0)
479+
qc_cliff.cx(0, 1)
480+
cliff = Clifford(qc_cliff)
481+
477482
qc = QuantumCircuit(2)
478483
qc.cx(0, 1)
479484
qc.append(random_clifford(1, seed=999), [1])
@@ -493,8 +498,8 @@ def test_from_circuit_with_all_types(self):
493498

494499
# Additionally, make sure that it produces the correct clifford.
495500
expected_clifford_dict = {
496-
"stabilizer": ["-IZX", "+XXZ", "-YYZ"],
497-
"destabilizer": ["-YYI", "-XZI", "-ZXY"],
501+
"stabilizer": ["-IZX", "+ZYZ", "+XZI"],
502+
"destabilizer": ["+XZZ", "-XII", "+IXY"],
498503
}
499504
expected_clifford = Clifford.from_dict(expected_clifford_dict)
500505
self.assertEqual(combined_clifford, expected_clifford)

test/python/quantum_info/operators/test_random.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,36 @@ def test_not_global_seed(self):
190190
rng_after = np.random.randint(1000, size=test_cases)
191191
self.assertFalse(np.all(rng_before == rng_after))
192192

193+
def test_cliffords_2q(self):
194+
"""Test that we get all 2-qubit Cliffords (actually symplectic
195+
matrices) with sufficiently many trials.
196+
"""
197+
seen = set()
198+
for seed in range(10000):
199+
cliff = random_clifford(2, seed)
200+
seen.add(cliff.symplectic_matrix.tobytes())
201+
self.assertEqual(len(seen), 720)
202+
203+
def test_clifford_2q_decompositions(self):
204+
"""Test that we get all possible CX-counts for 2q-random cliffords
205+
with sufficiently many trials.
206+
"""
207+
seen = set()
208+
for seed in range(100):
209+
cliff = random_clifford(2, seed)
210+
seen.add(cliff.to_circuit().count_ops().get("cx", 0))
211+
self.assertEqual(seen, {0, 1, 2, 3})
212+
213+
def test_clifford_3q_decompositions(self):
214+
"""Test that we get all possible CX-counts for 3q-random cliffords
215+
with sufficiently many trials.
216+
"""
217+
seen = set()
218+
for seed in range(10000):
219+
cliff = random_clifford(3, seed)
220+
seen.add(cliff.to_circuit().count_ops().get("cx", 0))
221+
self.assertEqual(seen, {0, 1, 2, 3, 4, 5, 6})
222+
193223

194224
@ddt
195225
class TestRandomPauliList(QiskitTestCase):

0 commit comments

Comments
 (0)