Skip to content

Commit 9e86d36

Browse files
optimize clifford benchmark circuit creation for a total 94.5% speedup (#6401)
This is a followup to #6392 and reduces circuit creation time (for 1000 cliffords and 50 qubits) to 0.213s from the original 3.886s (94.5% speedup) and the 2.148s (90% speedup) following #6392 ``` In [3]: import cirq.experiments.qubit_characterizations as ceq ...: import cirq ...: import time ...: import numpy as np ...: ...: num_cliffords = 1000 ...: qubits = cirq.LineQubit.range(50) ...: ...: cliffords = ceq._single_qubit_cliffords() ...: c1 = cliffords.c1_in_xy ...: t1 = time.time() ...: seq = ceq._create_parallel_rb_circuit(qubits, num_cliffords, c1) ...: t2 = time.time() ...: print(f'{t2-t1} s') 0.2055680751800537 s ```
1 parent b3e0eeb commit 9e86d36

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

cirq-core/cirq/experiments/qubit_characterizations.py

+15-12
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,9 @@ def single_qubit_randomized_benchmarking(
257257
A RandomizedBenchMarkResult object that stores and plots the result.
258258
"""
259259

260-
qubits = cast(Iterator['cirq.Qid'], (qubit,))
261260
result = parallel_single_qubit_randomized_benchmarking(
262261
sampler,
263-
qubits,
262+
(qubit,),
264263
use_xy_basis,
265264
num_clifford_range=num_clifford_range,
266265
num_circuits=num_circuits,
@@ -271,7 +270,7 @@ def single_qubit_randomized_benchmarking(
271270

272271
def parallel_single_qubit_randomized_benchmarking(
273272
sampler: 'cirq.Sampler',
274-
qubits: Iterator['cirq.Qid'],
273+
qubits: Sequence['cirq.Qid'],
275274
use_xy_basis: bool = True,
276275
*,
277276
num_clifford_range: Sequence[int] = tuple(
@@ -560,11 +559,16 @@ def _measurement(two_qubit_circuit: circuits.Circuit) -> np.ndarray:
560559

561560

562561
def _create_parallel_rb_circuit(
563-
qubits: Iterator['cirq.Qid'], num_cliffords: int, c1: list
562+
qubits: Sequence['cirq.Qid'], num_cliffords: int, c1: list
564563
) -> 'cirq.Circuit':
565-
circuits_to_zip = [_random_single_q_clifford(qubit, num_cliffords, c1) for qubit in qubits]
566-
circuit = circuits.Circuit.zip(*circuits_to_zip)
567-
return circuits.Circuit.from_moments(*circuit, ops.measure_each(*qubits))
564+
sequences_to_zip = [_random_single_q_clifford(qubit, num_cliffords, c1) for qubit in qubits]
565+
# Ensure each sequence has the same number of moments.
566+
num_moments = max(len(sequence) for sequence in sequences_to_zip)
567+
for q, sequence in zip(qubits, sequences_to_zip):
568+
if (n := len(sequence)) < num_moments:
569+
sequence.extend([ops.SingleQubitCliffordGate.I(q)] * (num_moments - n))
570+
moments = zip(*sequences_to_zip)
571+
return circuits.Circuit.from_moments(*moments, ops.measure_each(*qubits))
568572

569573

570574
def _indices_after_basis_rot(i: int, j: int) -> Tuple[int, Sequence[int], Sequence[int]]:
@@ -609,13 +613,12 @@ def _two_qubit_clifford_matrices(
609613

610614
def _random_single_q_clifford(
611615
qubit: 'cirq.Qid', num_cfds: int, cfds: Sequence[Sequence['cirq.Gate']]
612-
) -> 'cirq.Circuit':
616+
) -> List['cirq.Operation']:
613617
clifford_group_size = 24
618+
operations = [[gate(qubit) for gate in gates] for gates in cfds]
614619
gate_ids = list(np.random.choice(clifford_group_size, num_cfds))
615-
gate_sequence = [gate for gate_id in gate_ids for gate in cfds[gate_id]]
616-
gate_sequence.append(_reduce_gate_seq(gate_sequence) ** -1)
617-
circuit = circuits.Circuit(gate(qubit) for gate in gate_sequence)
618-
return circuit
620+
adjoint = _reduce_gate_seq([gate for gate_id in gate_ids for gate in cfds[gate_id]]) ** -1
621+
return [op for gate_id in gate_ids for op in operations[gate_id]] + [adjoint(qubit)]
619622

620623

621624
def _random_two_q_clifford(

cirq-core/cirq/sim/clifford/clifford_simulator_test.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,11 @@ def test_clifford_circuit_SHSYSHS():
324324
clifford_simulator = cirq.CliffordSimulator()
325325
state_vector_simulator = cirq.Simulator()
326326

327+
# workaround until #6402 is resolved.
328+
final_state_vector = state_vector_simulator.simulate(circuit).final_state_vector
329+
final_state_vector /= np.sqrt(np.linalg.norm(final_state_vector))
327330
np.testing.assert_almost_equal(
328-
clifford_simulator.simulate(circuit).final_state.state_vector(),
329-
state_vector_simulator.simulate(circuit).final_state_vector,
331+
clifford_simulator.simulate(circuit).final_state.state_vector(), final_state_vector
330332
)
331333

332334

0 commit comments

Comments
 (0)