<jupyter_start><jupyter_text>Interleaved Randomized Benchmarking* **Last Updated:** August 19, 2019* **Requires:** qiskit-terra 0.8, qiskit-ignis 0.1.2, qiskit-aer 0.2 Introduction**Interleaved Randomized Benchmarking** is a variant of the Randomized Benchmarking (RB) method that is used for benchmarking individual Clifford gates via randomization. The protocol consists of interleaving random gates between the given Clifford gate of interest. The protocol estimates the gate error of the given Clifford. The method is based on the paper *"Efficient measurement of quantum gate error by interleaved randomized benchmarking"*(https://arxiv.org/abs/1203.4550).This notebook gives an example for how to use the ``ignis.verification.randomized_benchmarking`` module in order to perform interleaved RB.<jupyter_code>#Import general libraries (needed for functions)
import numpy as np
import matplotlib.pyplot as plt
from IPython import display

#Import the RB Functions
import qiskit.ignis.verification.randomized_benchmarking as rb

#Import Qiskit classes classes
import qiskit
from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise.errors.standard_errors import depolarizing_error, thermal_relaxation_error<jupyter_output><empty_output><jupyter_text>Select the Parameters of the Interleaved RB RunFirst, wee need to choose the regular RB parameters:- **nseeds:** The number of seeds. For each seed you will get a separate list of output circuits in rb_circs.- **length_vector:** The length vector of Clifford lengths. Must be in ascending order. RB sequences of increasing length grow on top of the previous sequences.- **rb_pattern:** A list of the form [[i,j],[k],...] which will make simultaneous RB sequences where Qi,Qj are a 2-qubit RB sequence and Qk is a 1-qubit sequence, etc. The number of qubits is the sum of the entries. For 'regular' RB the qubit_pattern is just [[0]],[[0,1]].- **length_multiplier:** If this is an array it scales each rb_sequence by the multiplier.- **seed_offset:** What to start the seeds at (e.g. if we want to add more seeds later).- **align_cliffs:**  If true adds a barrier across all qubits in rb_pattern after each set of Cliffords.As well as another parameter for interleaved RB:- **interleaved_gates:** A list of gates of Clifford elements that will be interleaved. The length of the list would equal the length of the rb_pattern.In this example we have 3 qubits Q0,Q1,Q2. We are running 2Q RB (on qubits Q0,Q2) and 1Q RB (on qubit Q1) simultaneously, where there are twice as many 1Q Clifford gates.<jupyter_code>#Number of qubits
nQ = 3
#There are 3 qubits: Q0,Q1,Q2.
#Number of seeds (random sequences)
nseeds = 5
#Number of Cliffords in the sequence (start, stop, steps)
nCliffs = np.arange(1,200,20)
#2Q RB on Q0,Q2 and 1Q RB on Q1
rb_pattern = [[0,2],[1]]
#Do three times as many 1Q Cliffords
length_multiplier = [1,3]
#Interleaved Clifford gates (2-qubits and 1-qubit)
interleaved_gates = [['h 0', 'cx 0 1'],['x 0']]<jupyter_output><empty_output><jupyter_text>Generate Interleaved RB sequencesWe generate RB sequences. We start with a small example (so it doesn't take too long to run).In order to generate the RB sequences **rb_circs**, which is a list of lists of quantum circuits, we run the function `rb.randomized_benchmarking_seq`.This function returns:- **rb_original_circs:** A list of lists of circuits for the original RB sequences (separate list for each seed).- **xdata:** The Clifford lengths (with multiplier if applicable).As well as:- **rb_interleaved_circs**: A list of lists of circuits for the interleaved RB sequences (separate list for each seed).<jupyter_code>rb_opts = {}
rb_opts['length_vector'] = nCliffs
rb_opts['nseeds'] = nseeds
rb_opts['rb_pattern'] = rb_pattern
rb_opts['length_multiplier'] = length_multiplier
#rb_opts['align_cliffs'] = True
rb_opts['interleaved_gates'] = interleaved_gates
rb_original_circs, xdata, rb_interleaved_circs = rb.randomized_benchmarking_seq(**rb_opts)<jupyter_output><empty_output><jupyter_text>As an example, we print the circuit corresponding to the first original and interleaved RB sequences:<jupyter_code>#Original RB circuits
print (rb_original_circs[0][0])
#Interleaved RB circuits
print (rb_interleaved_circs[0][0])<jupyter_output>┌───┐┌─────┐┌───┐        ┌───┐ ┌───┐            ░ ┌───┐             »
qr_0: |0>┤ H ├┤ Sdg ├┤ H ├──■─────┤ X ├─┤ Z ├────────────░─┤ H ├───────■─────»
         ├───┤└──░──┘├───┤  │   ░ └─┬─┘┌┴───┴┐┌───┐┌───┐ ░ └─░─┘┌───┐  │   ░ »
qr_1: |0>┤ H ├───░───┤ X ├──┼───░───┼──┤ Sdg ├┤ H ├┤ Y ├─────░──┤ X ├──┼───░─»
         ├───┤ ┌───┐ ├───┤┌─┴─┐ ░   │  └┬───┬┘├───┤└───┘ ░   ░  └───┘┌─┴─┐ ░ »
qr_2: |0>┤ H ├─┤ H ├─┤ S ├┤ X ├─────■───┤ H ├─┤ S ├──────░───────────┤ X ├───»
         └───┘ └───┘ └───┘└───┘         └───┘ └───┘      ░           └───┘   »
 cr_0: 0 ════════════════════════════════════════════════════════════════════»
                                                                             »
 cr_1: 0 ════════════════════════════════════════════════════════════════════»
                                                                             »
 cr_2: 0 ════════════════════════════════════════════════════════════════════»
                                                    [...]<jupyter_text>Define the noise modelWe define a noise model for the simulator. To simulate decay, we add depolarizing error probabilities to the CNOT and U gates.<jupyter_code>noise_model = NoiseModel()
p1Q = 0.002
p2Q = 0.01
noise_model.add_all_qubit_quantum_error(depolarizing_error(p1Q, 1), 'u2')
noise_model.add_all_qubit_quantum_error(depolarizing_error(2*p1Q, 1), 'u3')
noise_model.add_all_qubit_quantum_error(depolarizing_error(p2Q, 2), 'cx')<jupyter_output><empty_output><jupyter_text>We can execute the original and interleaved RB sequences either using a Qiskit Aer Simulator (with some noise model) or using an IBMQ provider, and obtain a list of results, `result_list`.<jupyter_code>#Original RB circuits
backend = qiskit.Aer.get_backend('qasm_simulator')
basis_gates = ['u1','u2','u3','cx'] # use U,CX for now
shots = 200
original_result_list = []
original_qobj_list = []
import time
for rb_seed,rb_circ_seed in enumerate(rb_original_circs):
    print('Compiling seed %d'%rb_seed)
    new_rb_circ_seed = qiskit.compiler.transpile(rb_circ_seed, basis_gates=basis_gates)
    qobj = qiskit.compiler.assemble(new_rb_circ_seed, shots=shots)
    print('Simulating seed %d'%rb_seed)
    job = backend.run(qobj, noise_model=noise_model, backend_options={'max_parallel_experiments': 0})
    original_result_list.append(job.result())
    original_qobj_list.append(qobj)    
print("Finished Simulating Original Circuits")
#Interleaved RB circuits
backend = qiskit.Aer.get_backend('qasm_simulator')
basis_gates = ['u1','u2','u3','cx'] # use U,CX for now
shots = 200
interleaved_result_list = []
interleaved_qobj_list = []
import time
for rb_seed,rb_circ_seed in enumerate(rb_interleaved_circs):
    print('Compiling seed %d'%rb_seed)
    new_rb_circ_seed = qiskit.compiler.transpile(rb_circ_seed, basis_gates=basis_gates)
    qobj = qiskit.compiler.assemble(new_rb_circ_seed, shots=shots)
    print('Simulating seed %d'%rb_seed)
    job = backend.run(qobj, noise_model=noise_model, backend_options={'max_parallel_experiments': 0})
    interleaved_result_list.append(job.result())
    interleaved_qobj_list.append(qobj)    
print("Finished Simulating Interleaved Circuits")<jupyter_output>Compiling seed 0
Simulating seed 0
Compiling seed 1
Simulating seed 1
Compiling seed 2
Simulating seed 2
Compiling seed 3
Simulating seed 3
Compiling seed 4
Simulating seed 4
Finished Simulating Interleaved Circuits<jupyter_text>Fit the resultsWe fit the results of the original RB circuits and the interleaved RB circuits into an exponentially decaying function and obtain the *Errors per Clifford* $\alpha$ and $\alpha_C$ of the original and interleaved sequences, respectively.<jupyter_code>#Create the original and interleaved RB fitter
original_rb_fit = rb.RBFitter(original_result_list, xdata, rb_opts['rb_pattern'])
interleaved_rb_fit = rb.RBFitter(interleaved_result_list, xdata, rb_opts['rb_pattern'])<jupyter_output><empty_output><jupyter_text>Calculate the interleaved gate error fidelityFrom the values of $\alpha$ and $\alpha_C$ we obtain the gate error of the interleaved Clifford $c$, and $r_C=1-$(average gate fidelity of the interleaved Clifford $C$), is estimated by:$$ EPC^{est} = r_C^{est} = \frac{(2^n-1)(1-\alpha_C/\alpha)}{2^n}$$and must lie in the range given by certain systematic error bounds: $$[r_C^{est}-E,r_C^{est}+E]$$ for each of the patterns.<jupyter_code>#Calculate the joint fitter
joint_rb_fit = rb.InterleavedRBFitter(original_result_list, interleaved_result_list, xdata, rb_opts['rb_pattern'])
#Print the joint fitter parameters
for patt_ind, pattern in enumerate(rb_pattern):
    print ('pattern:', patt_ind, '-', len(pattern), 'qubit interleaved RB:', joint_rb_fit.fit_int[patt_ind])
#Plot the joint RB data
plt.figure(figsize=(15, 6))

for i in range(2):
    ax = plt.subplot(1, 2, i+1)
    pattern_ind = i

    # Plot the essence by calling plot_rb_data
    joint_rb_fit.plot_rb_data(pattern_ind, ax=ax, add_label=True, show_plt=False)

    # Add title and label
    ax.set_title('%d Qubit interleaved RB'%(len(rb_opts['rb_pattern'][i])), fontsize=18)

plt.show()
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1427363972530375, 'fraction_numerical': 0.014474379292128896, 'mean_word_length': 5.052429667519181, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 34, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '31986', 'license': 'Apache-2.0', 'n_tokens_mistral': 3457, 'n_tokens_neox': 3213, 'n_words': 985, 'path': 'docs/tutorials/advanced/Ignis/5b_interleaved_rb.ipynb', 'repo_name': 'andrea-simonetto/qiskit', 'size': '9465'}