-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Update RB to reduce the size of the generated circuits #7411
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 12 commits
895d9fb
266cfcd
401449e
0484795
cfcb3d6
39ba4b4
b69c910
1b59784
403a506
478b401
78e7675
22ccdeb
6bb8c90
256c43e
b552d21
66bc99a
f0ebcd2
cf27bb9
a5c4bfe
b3ce469
16911ff
047d1a8
91e2c1e
722e907
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 |
---|---|---|
|
@@ -36,6 +36,12 @@ | |
import cirq | ||
|
||
|
||
def _canonize_clifford_sequences( | ||
sequences: list[list[ops.SingleQubitCliffordGate]], | ||
) -> list[list[ops.SingleQubitCliffordGate]]: | ||
return [[_reduce_gate_seq(seq)] for seq in sequences] | ||
|
||
|
||
@dataclasses.dataclass | ||
class Cliffords: | ||
"""The single-qubit Clifford group, decomposed into elementary gates. | ||
|
@@ -336,7 +342,7 @@ def plot( | |
def single_qubit_randomized_benchmarking( | ||
sampler: cirq.Sampler, | ||
qubit: cirq.Qid, | ||
use_xy_basis: bool = True, | ||
use_xy_basis: bool = False, | ||
*, | ||
num_clifford_range: Sequence[int] = tuple(np.logspace(np.log10(5), 3, 5, dtype=int)), | ||
num_circuits: int = 10, | ||
|
@@ -387,16 +393,29 @@ def single_qubit_randomized_benchmarking( | |
return result.results_dictionary[qubit] | ||
|
||
|
||
def _gateset_selector( | ||
use_xy_basis: bool, xy_only: bool, xz_only: bool | ||
) -> list[list[ops.SingleQubitCliffordGate]]: | ||
clifford_group = _single_qubit_cliffords() | ||
sequences = clifford_group.c1_in_xy if use_xy_basis else clifford_group.c1_in_xz | ||
filter_seq = lambda seq: len(seq) == 2 | ||
if xy_only or xz_only: | ||
sequences = list(filter(filter_seq, sequences)) | ||
NoureldinYosri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _canonize_clifford_sequences(sequences) | ||
|
||
|
||
def parallel_single_qubit_randomized_benchmarking( | ||
sampler: cirq.Sampler, | ||
qubits: Sequence[cirq.Qid], | ||
use_xy_basis: bool = True, | ||
use_xy_basis: bool = False, | ||
*, | ||
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. What is the purpose of the "*," here? 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. it forces those other parameters to be keyword only 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. It doesn't make a lot of sense to have 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 agree it would be cleaner, but converting 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 there are many users of this RB implementation and I'm not worried about breaking old workflows here. |
||
num_clifford_range: Sequence[int] = tuple( | ||
np.logspace(np.log10(5), np.log10(1000), 5, dtype=int) | ||
), | ||
num_circuits: int = 10, | ||
repetitions: int = 1000, | ||
xy_only: bool = True, | ||
xz_only: bool = False, | ||
) -> ParallelRandomizedBenchmarkingResult: | ||
"""Clifford-based randomized benchmarking (RB) single qubits in parallel. | ||
|
||
|
@@ -413,13 +432,15 @@ def parallel_single_qubit_randomized_benchmarking( | |
num_circuits: The number of random circuits generated for each | ||
number of Cliffords. | ||
repetitions: The number of repetitions of each circuit. | ||
|
||
xy_only: whether to use only gates that have either an X or a Y component. | ||
if True, this excludes I, Z, Z/2, -Z/2. | ||
xz_only: whether to use only gates that have either an X or a Z component. | ||
if True, this excludes I, Y, Y/2, -Y/2. | ||
Returns: | ||
A dictionary from qubits to RandomizedBenchMarkResult objects. | ||
""" | ||
|
||
clifford_group = _single_qubit_cliffords() | ||
c1 = clifford_group.c1_in_xy if use_xy_basis else clifford_group.c1_in_xz | ||
c1 = _gateset_selector(use_xy_basis, xy_only, xz_only) | ||
|
||
# create circuits | ||
circuits_all: list[cirq.AbstractCircuit] = [] | ||
|
@@ -677,7 +698,7 @@ def _measurement(two_qubit_circuit: circuits.Circuit) -> np.ndarray: | |
|
||
|
||
def _create_parallel_rb_circuit( | ||
qubits: Sequence[cirq.Qid], num_cliffords: int, c1: list | ||
qubits: Sequence[cirq.Qid], num_cliffords: int, c1: list[list[ops.SingleQubitCliffordGate]] | ||
) -> cirq.Circuit: | ||
sequences_to_zip = [_random_single_q_clifford(qubit, num_cliffords, c1) for qubit in qubits] | ||
# Ensure each sequence has the same number of moments. | ||
|
@@ -732,9 +753,8 @@ def _two_qubit_clifford_matrices(q_0: cirq.Qid, q_1: cirq.Qid, cliffords: Cliffo | |
def _random_single_q_clifford( | ||
qubit: cirq.Qid, num_cfds: int, cfds: Sequence[Sequence[cirq.ops.SingleQubitCliffordGate]] | ||
) -> list[cirq.Operation]: | ||
clifford_group_size = 24 | ||
operations = [[gate.to_phased_xz_gate()(qubit) for gate in gates] for gates in cfds] | ||
gate_ids = np.random.choice(clifford_group_size, num_cfds).tolist() | ||
gate_ids = np.random.choice(len(cfds), num_cfds).tolist() | ||
adjoint = _reduce_gate_seq([gate for gate_id in gate_ids for gate in cfds[gate_id]]) ** -1 | ||
return [op for gate_id in gate_ids for op in operations[gate_id]] + [ | ||
adjoint.to_phased_xz_gate()(qubit) | ||
|
Uh oh!
There was an error while loading. Please reload this page.
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.
That interface has been around since #1533. Is there enough benefit from the new default to risk breaking any callers that expect the old value?
Also we have some callers of single_qubit_randomized_benchmarking and parallel_single_qubit_randomized_benchmarking in cirq sources that do not pass
use_xy_basis
.Would they still work as intended?
I suggest to leave the default as is in this PR and if there is a strong argument for its change, do so in a separate PR (and label it as "BREAKING CHANGE").
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.
to me, it is fine either way. @eliottrosenberg what do you think?
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.
We should definitely change this (as Nour does here) in order to match the default behavior of the internal implementation of RB. I don't have a preference as to whether it is in this PR or a different one. @pavoljuhas I doubt that a lot of people are using this, so I'm not worried about breaking changes.
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.
@eliottrosenberg we decided to create a new method to run RB that has the correct default values and deprecate the old methods.
Uh oh!
There was an error while loading. Please reload this page.
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.
I think that is probably overkill, but if you insist, it's ok.