Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
921c185
add mirror RB experiment and analysis files
albertzhu01 Jul 11, 2022
9cd7074
edit appropriate mirrorRB-relevant files for PR
albertzhu01 Jul 11, 2022
2de778b
remove prints and add paper ref
paco-ri Jul 12, 2022
a28e6d2
update docstrings
albertzhu01 Jul 11, 2022
9d440e8
delete commented series code
albertzhu01 Jul 11, 2022
8d656b6
fix pygsti version
albertzhu01 Jul 12, 2022
b0432fd
remove outcomes setting
albertzhu01 Jul 12, 2022
e1de0e4
cleaned RB tutorial
paco-ri Jul 12, 2022
859a94e
move coupling map outside loop, delete elements_without_inv and int_c…
albertzhu01 Jul 12, 2022
c1444ae
reformat files with black and lint
albertzhu01 Jul 12, 2022
6857a48
moved Clifford sampling in edgegrab algo
paco-ri Jul 12, 2022
8445f4a
use full connectivity for coupling map if coupling map is not provided
albertzhu01 Aug 8, 2022
63f171c
changed AnalysisResult imports
paco-ri Sep 1, 2022
bbf111f
edited BitGenerator and SeedSequence imports
paco-ri Sep 7, 2022
2308072
removed MirrorRBPyGSTi from library init file
paco-ri Sep 7, 2022
ebfa4d6
fix full connectivity map generation code
albertzhu01 Oct 31, 2022
de33876
remove MirrorRBPyGSTi from mirror_rb_experiment.py, rb tutorial, and …
albertzhu01 Oct 31, 2022
6fccca1
fix coupling map full connectivity generation and update aer imports …
albertzhu01 Nov 1, 2022
d2f8ff9
reformat imports (temporarily) to pass lint with merged code from ups…
albertzhu01 Nov 3, 2022
a7b7a70
merged main branch
coruscating Jan 31, 2023
20b36db
added edge grab docstring
coruscating Feb 24, 2023
c8c8a7b
moved sampler to its own file
coruscating Feb 25, 2023
ea53a5d
updated edgegrab
coruscating Feb 28, 2023
07b4b28
coupling map
coruscating Feb 28, 2023
31f565e
updated release note
coruscating Mar 2, 2023
41f9e81
partial refactoring
coruscating Mar 11, 2023
1f58ffb
fix rebase errors
coruscating Mar 11, 2023
961068d
update docs and remove edgegrab from utils
coruscating Mar 14, 2023
7d79339
changed 1Q from integer to clifford
coruscating Mar 15, 2023
e82df72
merge main
coruscating Mar 15, 2023
e3c9b61
fixed circuit length
coruscating Mar 16, 2023
e66a58d
fix rng and force default transpile
coruscating Mar 16, 2023
52ce46b
fix bugs to pass tests
coruscating Mar 17, 2023
f06dbc9
restored some RB changes and fixed tests
coruscating Mar 17, 2023
e69701d
updated manual
coruscating Mar 17, 2023
e6f8a07
replaced missing function
coruscating Mar 19, 2023
7651798
rewrote circuit generation logic and sampler
coruscating Mar 21, 2023
400a993
update 2q+ code
coruscating Mar 21, 2023
97a746d
fixed wrong indexing for general coupling maps
coruscating Mar 22, 2023
b32d331
lint and improve manual
coruscating Mar 22, 2023
d589aa6
Merge remote-tracking branch 'upstream/main' into mirrorrb-rebased
coruscating Mar 22, 2023
c70e150
update manual
coruscating Mar 22, 2023
a6c8ff8
refactored sampling utils and added tests
coruscating Mar 22, 2023
999bd6f
added distribution property to `MirrorRB`
coruscating Mar 23, 2023
3407385
merged main
coruscating Mar 23, 2023
3b0ae70
lint and fix docs
coruscating Mar 23, 2023
d318e51
fix doc links
coruscating Mar 23, 2023
530e5b6
merge main
coruscating Mar 23, 2023
fb23e99
Update tests
coruscating Mar 23, 2023
7224f59
fix nonlocal test
coruscating Mar 23, 2023
2a0f0c2
Merge remote-tracking branch 'upstream/main' into mirrorrb-rebased
coruscating Mar 24, 2023
09fe450
address review comments
coruscating Mar 24, 2023
4951cb1
change sampler output to list of named tuple
coruscating Mar 26, 2023
585c053
change gate distribution to named tuple
coruscating Mar 27, 2023
c209d1e
merge main
coruscating Mar 27, 2023
3812049
refactored experiment options
coruscating Mar 27, 2023
3070431
Merge remote-tracking branch 'upstream/main' into mirrorrb-rebased
coruscating Mar 27, 2023
d423e58
subclass`MirrorRBAnalysis` from `RBAnalysis`
coruscating Mar 27, 2023
b71d098
change y-axis option to `analyzed_quantity`
coruscating Mar 28, 2023
0510478
changed to `CouplingMap` type and added validation
coruscating Mar 28, 2023
1c98049
added data processor node for analysis
coruscating Mar 28, 2023
fb41d6d
change sampler to return a generator
coruscating Mar 28, 2023
7710f7c
Address review comments and fix tests
coruscating Mar 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
from qiskit.providers.backend import Backend
from qiskit.providers.options import Options
from qiskit.exceptions import QiskitError
from qiskit.circuit.library import CXGate, CYGate, CZGate, ECRGate, SwapGate, iSwapGate
from qiskit.transpiler import CouplingMap
from qiskit.circuit.library import CXGate, CYGate, CZGate, ECRGate, SwapGate

from .standard_rb import StandardRB, SequenceElementType
from .mirror_rb_analysis import MirrorRBAnalysis
Expand All @@ -43,7 +44,7 @@
)

# two qubit gates that are their own inverse
_self_adjoint_gates = [CXGate, CYGate, CZGate, ECRGate, SwapGate, iSwapGate]
_self_adjoint_gates = [CXGate, CYGate, CZGate, ECRGate, SwapGate]


class MirrorRB(StandardRB):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like you override almost all protected methods of the StandardRB (except for the transpile logic that manages pulse gates and gate counts). If you really need to override every method and you cannot find any possibility for partly reusing base class code, probably we should design better base class for RB experiments (or, maybe RB Metaclass?). Just curious. @itoko

Copy link
Contributor

@itoko itoko Mar 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good discussion point. Ideally, I prefer MirrorRB should be a subclass of BaseExperiment (not StandardRB). I don't want to have a base class for RB because I prefer delegation (helper functions) rather than inheritance (subclassing) in order to reuse implementation. So it would be better if we could introduce helper functions that have what is currently implemented in _transpiled_circuits() and _get_basis_gates, and use them to implement _transpiled_circuits() for StandardRB and MirrorRB. Anyway, such kind of refactoring should be done later (maybe in a follow-up PR before release).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts on this point @coruscating ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that MirrorRB is different enough from StandardRB that it's not really worth subclassing directly. I think helper functions sound good. Let's do it in a follow-up PR as you suggested.

Expand Down Expand Up @@ -140,9 +141,6 @@ def __init__(
if not all(length % 2 == 0 for length in lengths):
raise QiskitError("All lengths must be even")

if two_qubit_gate_density < 0 or two_qubit_gate_density > 1:
raise QiskitError("Two-qubit gate density must be between 0 and 1.")

super().__init__(
physical_qubits,
lengths,
Expand Down Expand Up @@ -197,6 +195,7 @@ def _default_experiment_options(cls) -> Options:
sampler_opts={},
inverting_pauli_layer=False,
)
options.set_validator(field="two_qubit_gate_density", validator_value=(0, 1))

return options

Expand Down Expand Up @@ -228,17 +227,11 @@ def _set_distribution_options(self):
# get backend coupling map and create coupling map for physical qubits converted
# to qubits 0, 1...n
if self.backend and self._backend_data.coupling_map:
coupling_map = self._backend_data.coupling_map
coupling_map = CouplingMap(self._backend_data.coupling_map)
else:
coupling_map = list(itertools.permutations(range(max(self.physical_qubits) + 1), 2))
qmap = {self.physical_qubits[i]: i for i in range(len(self.physical_qubits))}
experiment_coupling_map = []

for edge in coupling_map:
if edge[0] in self.physical_qubits and edge[1] in self.physical_qubits:
experiment_coupling_map.append((qmap[edge[0]], qmap[edge[1]]))
coupling_map = CouplingMap.from_full(len(self.physical_qubits))

self._distribution.coupling_map = experiment_coupling_map
self._distribution.coupling_map = coupling_map.reduce(self.physical_qubits)

# Adjust the density based on whether the pauli layers are in
if self.experiment_options.pauli_randomize:
Expand Down Expand Up @@ -336,14 +329,11 @@ def _sample_sequences(self) -> List[Sequence[SequenceElementType]]:

# Add start and end cliffords if set by user
if self.experiment_options.start_end_clifford:
cseq = []
clifford_layers = clifford_sampler(range(self.num_qubits), length=1)
cseq.append(clifford_layers[0])
cseq.extend(seq)
cseq.append(self._inverse_layer(clifford_layers[0]))
seq.insert(0, clifford_layers[0])
seq.append(self._inverse_layer(clifford_layers[0]))
if not self.experiment_options.full_sampling:
build_seq_lengths = [length + 2 for length in build_seq_lengths]
seq = cseq

if self.experiment_options.full_sampling:
sequences.append(seq)
Expand Down Expand Up @@ -381,8 +371,6 @@ def _sequences_to_circuits(
circ.append(Barrier(self.num_qubits), circ.qubits)
circ.metadata = {
"xval": self.experiment_options.lengths[i % len(self.experiment_options.lengths)],
"group": "Clifford",
"physical_qubits": self.physical_qubits,
"target": compute_target_bitstring(circ_target),
"inverting_pauli_layer": self.experiment_options.inverting_pauli_layer,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,19 @@ def __init__(
"""
super().__init__(seed)
self._gate_distribution = gate_distribution
self._coupling_map = coupling_map
self.coupling_map = coupling_map

@property
def coupling_map(self):
def coupling_map(self) -> CouplingMap:
"""The coupling map of the system to sample over."""
return self._coupling_map

@coupling_map.setter
def coupling_map(self, coupling_map):
self._coupling_map = coupling_map
def coupling_map(self, coupling_map: Union[List[List[int]], CouplingMap]) -> None:
try:
self._coupling_map = CouplingMap(coupling_map)
except (ValueError, TypeError) as exc:
raise TypeError("Invalid coupling map provided.") from exc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


def __call__(
self,
Expand Down Expand Up @@ -338,12 +341,12 @@ def __call__(
)
]

if not isinstance(self.coupling_map, List) or isinstance(self.coupling_map, CouplingMap):
raise QiskitError("The coupling map must be set correctly before sampling.")

layer_list = []

for _ in range(length):
all_edges = self.coupling_map[:] # make copy of coupling map from which we pop edges
all_edges = self.coupling_map.get_edges()[
:
] # make copy of coupling map from which we pop edges
selected_edges = []
while all_edges:
rand_edge = all_edges.pop(self._rng.integers(len(all_edges)))
Expand Down
2 changes: 1 addition & 1 deletion test/library/randomized_benchmarking/test_mirror_rb.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ def test_add_more_circuit_yields_lower_variance(self):
)
def test_invalid_configuration(self, configs):
"""Test raise error when creating experiment with invalid configs."""
self.assertRaises(QiskitError, rb.MirrorRB, **configs)
self.assertRaises((QiskitError, ValueError), rb.MirrorRB, **configs)

@data(
{
Expand Down