Skip to content

Commit ff4828a

Browse files
dcmckayibmwshanks
andauthored
Unitary Layer RB (#1561)
This PR adds a new class to do layer style RB with an arbitrary set of 2Q unitary circuits for the entangling layer. Example usage which will perform RB with 10 different RZZ angles. ``` rzz_gate_lst = [] for i in range(10): qc = QuantumCircuit(2) qc.rzz(np.pi/2/10*(i+1),0,1) print(np.pi/2/10*(i+1)) rzz_gate_lst.append(qc.to_instruction()) rb_obj = LayerFidelityUnitary(physical_qubits = [0,1,2,3], two_qubit_layers = [[[0,1],[2,3]]], two_qubit_gates=rzz_gate_lst, lengths = [2,10,100], backend=backend, num_samples=1, seed=1, layer_barrier=False) ``` --------- Co-authored-by: Will Shanks <[email protected]>
1 parent 3de4cc2 commit ff4828a

File tree

7 files changed

+781
-10
lines changed

7 files changed

+781
-10
lines changed

qiskit_experiments/library/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
~randomized_benchmarking.StandardRB
3838
~randomized_benchmarking.InterleavedRB
3939
~randomized_benchmarking.LayerFidelity
40+
~randomized_benchmarking.LayerFidelityUnitary
4041
~tomography.TomographyExperiment
4142
~tomography.StateTomography
4243
~tomography.ProcessTomography
@@ -121,7 +122,12 @@
121122
ZZRamsey,
122123
MultiStateDiscrimination,
123124
)
124-
from .randomized_benchmarking import StandardRB, InterleavedRB
125+
from .randomized_benchmarking import (
126+
StandardRB,
127+
InterleavedRB,
128+
LayerFidelity,
129+
LayerFidelityUnitary,
130+
)
125131
from .tomography import (
126132
TomographyExperiment,
127133
StateTomography,

qiskit_experiments/library/randomized_benchmarking/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
StandardRB
2727
InterleavedRB
2828
LayerFidelity
29+
LayerFidelityUnitary
2930
3031
3132
Analysis
@@ -64,4 +65,5 @@
6465
from .rb_utils import RBUtils
6566
from .clifford_synthesis import RBDefaultCliffordSynthesis
6667
from .layer_fidelity import LayerFidelity
68+
from .layer_fidelity_unitary import LayerFidelityUnitary
6769
from .layer_fidelity_analysis import LayerFidelityAnalysis

qiskit_experiments/library/randomized_benchmarking/clifford_utils.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,17 @@ def _transpile_clifford_circuit(
5555
return _apply_qubit_layout(_decompose_clifford_ops(circuit), physical_qubits=physical_qubits)
5656

5757

58-
def _decompose_clifford_ops(circuit: QuantumCircuit) -> QuantumCircuit:
59-
# Simplified QuantumCircuit.decompose, which decomposes only Clifford ops
58+
def _decompose_clifford_ops(circuit: QuantumCircuit, all_circs: bool = False) -> QuantumCircuit:
59+
# Simplified QuantumCircuit.decompose, which decomposes Clifford
60+
# ops into the underlying circuit elements. If all_circs is True then this will
61+
# also decompose operations starting with "circuit"
6062
res = circuit.copy_empty_like()
6163
if hasattr(circuit, "_parameter_table"):
6264
res._parameter_table = circuit._parameter_table
6365
for inst in circuit:
64-
if inst.operation.name.startswith("Clifford"): # Decompose
66+
if inst.operation.name.startswith("Clifford") or (
67+
all_circs and inst.operation.name.startswith("circuit")
68+
): # Decompose
6569
rule = inst.operation.definition.data
6670
if len(rule) == 1 and len(inst.qubits) == len(rule[0].qubits):
6771
if inst.operation.definition.global_phase:

qiskit_experiments/library/randomized_benchmarking/layer_fidelity.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,21 +347,22 @@ def __validate_basis_gates(self) -> None:
347347
if not self.backend:
348348
return
349349
opts = self.experiment_options
350+
target = self.backend.target
350351
# validate two_qubit_gate if it is set
351352
if opts.two_qubit_gate:
352-
if opts.two_qubit_gate not in self.backend.target.operation_names:
353+
if opts.two_qubit_gate not in target.operation_names:
353354
raise QiskitError(f"two_qubit_gate {opts.two_qubit_gate} is not in backend.target")
354355
for two_q_layer in opts.two_qubit_layers:
355356
for qpair in two_q_layer:
356-
if not self.backend.target.instruction_supported(opts.two_qubit_gate, qpair):
357+
if not target.instruction_supported(opts.two_qubit_gate, qpair):
357358
raise QiskitError(f"{opts.two_qubit_gate}{qpair} is not in backend.target")
358359
# validate one_qubit_basis_gates if it is set
359360
for gate in opts.one_qubit_basis_gates or []:
360-
if gate not in self.backend.target.operation_names:
361+
if gate not in target.operation_names:
361362
raise QiskitError(f"{gate} in one_qubit_basis_gates is not in backend.target")
362363
for gate in opts.one_qubit_basis_gates or []:
363364
for q in self.physical_qubits:
364-
if not self.backend.target.instruction_supported(gate, (q,)):
365+
if not target.instruction_supported(gate, (q,)):
365366
raise QiskitError(f"{gate}({q}) is not in backend.target")
366367

367368
def __residual_qubits(self, two_qubit_layer):

0 commit comments

Comments
 (0)