-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add parallel randomized benchmarking #6382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
c4f52a4
1e0a1b4
21b41d5
489cd09
5be6786
f8b1c42
d03db79
207f1e9
ca5d0b1
dd37885
4bbdc2b
4029c3a
bfed7c7
9c57fa6
4c1a538
6008b7f
188eaa7
609706a
796d5b7
aeff626
9980416
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -230,6 +230,70 @@ def single_qubit_randomized_benchmarking( | |||||
| return RandomizedBenchMarkResult(num_clifford_range, gnd_probs) | ||||||
|
|
||||||
|
|
||||||
| def parallel_single_qubit_randomized_benchmarking( | ||||||
| sampler: 'cirq.Sampler', | ||||||
| use_xy_basis: bool = True, | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason this is before the kwargs cut-off?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was following the same format as in |
||||||
| *, | ||||||
| qubits: Optional[Iterator['cirq.GridQubit']] = None, | ||||||
| num_clifford_range: Sequence[int] = [5, 18, 70, 265, 1000], | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| num_circuits: int = 10, | ||||||
| repetitions: int = 600, | ||||||
| ) -> dict: | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| """Clifford-based randomized benchmarking (RB) single qubits in parallel. | ||||||
|
|
||||||
| This is the same as `single_qubit_randomized_benchmarking` except on all | ||||||
| of the specified qubits in parallel, i.e. with the individual randomized | ||||||
| benchmarking circuits zipped together. | ||||||
|
|
||||||
| Args: | ||||||
| sampler: The quantum engine or simulator to run the circuits. | ||||||
| use_xy_basis: Determines if the Clifford gates are built with x and y | ||||||
| rotations (True) or x and z rotations (False). | ||||||
| qubits: The qubits to benchmark. If None, benchmark all of the qubits. | ||||||
| num_clifford_range: The different numbers of Cliffords in the RB study. | ||||||
| num_circuits: The number of random circuits generated for each | ||||||
| number of Cliffords. | ||||||
| repetitions: The number of repetitions of each circuit. | ||||||
|
|
||||||
| Returns: | ||||||
| A dictionary from qubits to RandomizedBenchMarkResult objects. | ||||||
| """ | ||||||
|
|
||||||
| if qubits is None: # pragma: no cover | ||||||
| try: | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| device = sampler.processor.get_device() # type: ignore | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| except: | ||||||
| device = sampler.device # type: ignore | ||||||
| qubits = device.metadata.qubit_set | ||||||
|
|
||||||
| cliffords = _single_qubit_cliffords() | ||||||
| c1 = cliffords.c1_in_xy if use_xy_basis else cliffords.c1_in_xz | ||||||
| cfd_mats = np.array([_gate_seq_to_mats(gates) for gates in c1]) | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| # create circuits | ||||||
| circuits_all = [] | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: call this
Suggested change
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think I should call this |
||||||
| for num_cfds in num_clifford_range: | ||||||
| for _ in range(num_circuits): | ||||||
| circuits_all.append(_create_parallel_rb_circuit(qubits, num_cfds, c1, cfd_mats)) | ||||||
|
NoureldinYosri marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| # run circuits | ||||||
| results_all = sampler.run_batch(circuits_all, repetitions=repetitions) | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| gnd_probs: dict = {q: [] for q in qubits} | ||||||
| idx = 0 | ||||||
| for num_cfds in num_clifford_range: | ||||||
| excited_probs_l: dict = {q: [] for q in qubits} | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| for _ in range(num_circuits): | ||||||
| results = results_all[idx][0] | ||||||
| for qubit in qubits: | ||||||
| excited_probs_l[qubit].append( | ||||||
| np.mean(results.measurements[f"q{qubit.row}_{qubit.col}"]) | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| ) | ||||||
| idx += 1 | ||||||
| for qubit in qubits: | ||||||
| gnd_probs[qubit].append(1.0 - np.mean(excited_probs_l[qubit])) | ||||||
| return {q: RandomizedBenchMarkResult(num_clifford_range, gnd_probs[q]) for q in qubits} | ||||||
|
|
||||||
|
|
||||||
| def two_qubit_randomized_benchmarking( | ||||||
| sampler: 'cirq.Sampler', | ||||||
| first_qubit: 'cirq.Qid', | ||||||
|
|
@@ -464,6 +528,18 @@ def _measurement(two_qubit_circuit: circuits.Circuit) -> np.ndarray: | |||||
| return TomographyResult(rho) | ||||||
|
|
||||||
|
|
||||||
| def _create_parallel_rb_circuit( | ||||||
| qubits: Iterator['cirq.GridQubit'], num_cfds: int, c1: list, cfd_mats: np.ndarray | ||||||
| ) -> 'cirq.Circuit': | ||||||
| circuits_to_zip = [_random_single_q_clifford(qubit, num_cfds, c1, cfd_mats) for qubit in qubits] | ||||||
| circuit = circuits.Circuit.zip(*circuits_to_zip) | ||||||
| measure_moment = circuits.Moment( | ||||||
| ops.measure_each(*qubits, key_func=lambda q: f"q{q.row}_{q.col}") # type: ignore | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| ) | ||||||
| circuit_with_meas = circuits.Circuit.from_moments(*(list(circuit.moments) + [measure_moment])) | ||||||
|
eliottrosenberg marked this conversation as resolved.
Outdated
|
||||||
| return circuit_with_meas | ||||||
|
|
||||||
|
|
||||||
| def _indices_after_basis_rot(i: int, j: int) -> Tuple[int, Sequence[int], Sequence[int]]: | ||||||
| mat_idx = 3 * (3 * i + j) | ||||||
| q_0_i = 3 - i | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OOC, would it be possible to put this in the existing
single_qubit_randomized_benchmarkingmodule? Seems like it's basically the same thing and there could be opportunities for code reuse. The fact that one is running in parallel on multiple qubits is a minor details (the existing single-qubit code could just become a special case of the parallel code).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I changed it so that
single_qubit_randomized_benchmarkingis now a wrapper forparallel_single_qubit_randomized_benchmarking. What do you think?