-
Notifications
You must be signed in to change notification settings - Fork 131
Interleaved RB #28
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
Merged
coruscating
merged 23 commits into
qiskit-community:main
from
gadial:interleaved_rb_experiment
May 12, 2021
Merged
Interleaved RB #28
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
3039311
Beginning of interleaved RB and several fixes to related classes
gadial 12fd048
Small refactor to mean_xy_data
gadial aaaffe1
Updated mean_xy_data to support multi series
gadial 5c91db6
Using multi_curve_fit in interleaved analysis (not working correctly …
gadial 83d3b7b
multi_curve_fit seems to work now
gadial d609137
Anaylsis results for interleaved rb
gadial 56e3bb3
Linting
gadial 27a1216
Linting
gadial 9804762
Linting
gadial fdf9deb
Added interleaved RB to the notebook
gadial e111d3e
Small fixes
gadial 09a6938
Moved RB notebook to tutorial folder
gadial ef7c0d9
Linting
gadial 319d5da
Switch to Chris' version of multi_mean_xy_data
gadial 738e688
Small fixes
gadial 51494f8
Added equations
gadial ca827f1
Linting
gadial 00d3b5b
Merge branch 'main' into interleaved_rb_experiment
gadial a61bda0
Running black
gadial f0ec6c3
Merge branch 'main' into interleaved_rb_experiment
gadial fae6824
Bugfixes
gadial 45f4852
Added interleaved analysis to __init__
gadial 895d76b
Merge branch 'main' into interleaved_rb_experiment
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
176 changes: 176 additions & 0 deletions
176
qiskit_experiments/randomized_benchmarking/interleaved_rb_analysis.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,176 @@ | ||
| # This code is part of Qiskit. | ||
| # | ||
| # (C) Copyright IBM 2021. | ||
| # | ||
| # This code is licensed under the Apache License, Version 2.0. You may | ||
| # obtain a copy of this license in the LICENSE.txt file in the root directory | ||
| # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
| # | ||
| # Any modifications or derivative works of this code must retain this | ||
| # copyright notice, and modified files need to carry a notice indicating | ||
| # that they have been altered from the originals. | ||
| """ | ||
| Interleaved RB analysis class. | ||
| """ | ||
| from typing import Optional, List | ||
| import numpy as np | ||
| from qiskit_experiments.analysis.curve_fitting import ( | ||
| process_multi_curve_data, | ||
| multi_curve_fit, | ||
| ) | ||
|
|
||
| from qiskit_experiments.analysis.plotting import plot_curve_fit, plot_scatter, plot_errorbar | ||
| from qiskit_experiments.analysis.data_processing import ( | ||
| level2_probability, | ||
| multi_mean_xy_data, | ||
| ) | ||
| from .rb_analysis import RBAnalysis | ||
|
|
||
| try: | ||
| from matplotlib import pyplot as plt | ||
|
|
||
| HAS_MATPLOTLIB = True | ||
| except ImportError: | ||
| HAS_MATPLOTLIB = False | ||
|
|
||
|
|
||
| class InterleavedRBAnalysis(RBAnalysis): | ||
| r"""Interleaved RB Analysis class. | ||
| According to the paper: "Efficient measurement of quantum gate | ||
| error by interleaved randomized benchmarking" (arXiv:1203.4550) | ||
|
|
||
| The epc estimate is obtained using the equation | ||
| :math:`r_{\mathcal{C}}^{\text{est}}= | ||
| \frac{\left(d-1\right)\left(1-p_{\overline{\mathcal{C}}}/p\right)}{d}` | ||
|
|
||
| The error bounds are given by | ||
| :math:`E=\min\left\{ \begin{array}{c} | ||
| \frac{\left(d-1\right)\left[\left|p-p_{\overline{\mathcal{C}}}/p\right|+\left(1-p\right)\right]}{d}\\ | ||
| \frac{2\left(d^{2}-1\right)\left(1-p\right)}{pd^{2}}+\frac{4\sqrt{1-p}\sqrt{d^{2}-1}}{p} | ||
| \end{array}\right.` | ||
| """ | ||
|
|
||
| # pylint: disable=invalid-name | ||
| def _run_analysis( | ||
| self, | ||
| experiment_data, | ||
| p0: Optional[List[float]] = None, | ||
| plot: bool = True, | ||
| ax: Optional["AxesSubplot"] = None, | ||
| ): | ||
| def data_processor(datum): | ||
| return level2_probability(datum, datum["metadata"]["ylabel"]) | ||
|
|
||
| num_qubits = len(experiment_data.data[0]["metadata"]["qubits"]) | ||
| series, x, y, sigma = process_multi_curve_data(experiment_data.data, data_processor) | ||
| series, xdata, ydata, ydata_sigma = multi_mean_xy_data(series, x, y, sigma) | ||
|
|
||
| def fit_fun_standard(x, a, alpha_std, _, b): | ||
| return a * alpha_std ** x + b | ||
|
|
||
| def fit_fun_interleaved(x, a, _, alpha_int, b): | ||
| return a * alpha_int ** x + b | ||
|
|
||
| std_idx = series == 0 | ||
| std_xdata = xdata[std_idx] | ||
| std_ydata = ydata[std_idx] | ||
| std_ydata_sigma = ydata_sigma[std_idx] | ||
| p0_std = self._p0(std_xdata, std_ydata, num_qubits) | ||
|
|
||
| int_idx = series == 1 | ||
| int_xdata = xdata[int_idx] | ||
| int_ydata = ydata[int_idx] | ||
| int_ydata_sigma = ydata_sigma[int_idx] | ||
| p0_int = self._p0(int_xdata, int_ydata, num_qubits) | ||
|
|
||
| p0 = ( | ||
| np.mean([p0_std[0], p0_int[0]]), | ||
| p0_std[1], | ||
| p0_int[1], | ||
| np.mean([p0_std[2], p0_int[2]]), | ||
| ) | ||
|
|
||
| analysis_result = multi_curve_fit( | ||
| [fit_fun_standard, fit_fun_interleaved], | ||
| series, | ||
| xdata, | ||
| ydata, | ||
| p0, | ||
| ydata_sigma, | ||
| bounds=([0, 0, 0, 0], [1, 1, 1, 1]), | ||
| ) | ||
|
|
||
| # Add EPC data | ||
| nrb = 2 ** num_qubits | ||
| scale = (nrb - 1) / (2 ** nrb) | ||
| _, alpha, alpha_c, _ = analysis_result["popt"] | ||
| _, alpha_err, alpha_c_err, _ = analysis_result["popt_err"] | ||
|
|
||
| # Calculate epc_est (=r_c^est) - Eq. (4): | ||
| epc_est = scale * (1 - alpha_c / alpha) | ||
| # Calculate the systematic error bounds - Eq. (5): | ||
| systematic_err_1 = scale * (abs(alpha - alpha_c / alpha) + (1 - alpha)) | ||
| systematic_err_2 = ( | ||
| 2 * (nrb * nrb - 1) * (1 - alpha) / (alpha * nrb * nrb) | ||
| + 4 * (np.sqrt(1 - alpha)) * (np.sqrt(nrb * nrb - 1)) / alpha | ||
| ) | ||
| systematic_err = min(systematic_err_1, systematic_err_2) | ||
| systematic_err_l = epc_est - systematic_err | ||
| systematic_err_r = epc_est + systematic_err | ||
|
|
||
| alpha_err_sq = (alpha_err / alpha) ** 2 | ||
| alpha_c_err_sq = (alpha_c_err / alpha_c) ** 2 | ||
| epc_est_err = ( | ||
| ((nrb - 1) / nrb) * (alpha_c / alpha) * (np.sqrt(alpha_err_sq + alpha_c_err_sq)) | ||
| ) | ||
|
|
||
| analysis_result["EPC"] = epc_est | ||
| analysis_result["EPC_err"] = epc_est_err | ||
| analysis_result["systematic_err"] = systematic_err | ||
| analysis_result["systematic_err_L"] = systematic_err_l | ||
| analysis_result["systematic_err_R"] = systematic_err_r | ||
| analysis_result["plabels"] = ["A", "alpha", "alpha_c", "B"] | ||
|
|
||
| if plot: | ||
| ax = plot_curve_fit(fit_fun_standard, analysis_result, ax=ax) | ||
| ax = plot_curve_fit(fit_fun_interleaved, analysis_result, ax=ax) | ||
| ax = plot_scatter(std_xdata, std_ydata, ax=ax) | ||
| ax = plot_scatter(int_xdata, int_ydata, ax=ax) | ||
| ax = plot_errorbar(std_xdata, std_ydata, std_ydata_sigma, ax=ax) | ||
| ax = plot_errorbar(int_xdata, int_ydata, int_ydata_sigma, ax=ax) | ||
| self._format_plot(ax, analysis_result) | ||
| analysis_result.plt = plt | ||
|
|
||
| return analysis_result, None | ||
|
|
||
| @classmethod | ||
| def _format_plot(cls, ax, analysis_result, add_label=True): | ||
| """Format curve fit plot""" | ||
| # Formatting | ||
| ax.tick_params(labelsize=14) | ||
| ax.set_xlabel("Clifford Length", fontsize=16) | ||
| ax.set_ylabel("Ground State Population", fontsize=16) | ||
| ax.grid(True) | ||
|
|
||
| if add_label: | ||
| alpha = analysis_result["popt"][1] | ||
| alpha_c = analysis_result["popt"][2] | ||
| alpha_err = analysis_result["popt_err"][1] | ||
| alpha_c_err = analysis_result["popt_err"][2] | ||
| epc = analysis_result["EPC"] | ||
| epc_err = analysis_result["EPC_err"] | ||
| box_text = "\u03B1:{:.4f} \u00B1 {:.4f}".format(alpha, alpha_err) | ||
| box_text += "\n\u03B1_c:{:.4f} \u00B1 {:.4f}".format(alpha_c, alpha_c_err) | ||
| box_text += "\nEPC: {:.4f} \u00B1 {:.4f}".format(epc, epc_err) | ||
| bbox_props = dict(boxstyle="square,pad=0.3", fc="white", ec="black", lw=1) | ||
| ax.text( | ||
| 0.6, | ||
| 0.9, | ||
| box_text, | ||
| ha="center", | ||
| va="center", | ||
| size=14, | ||
| bbox=bbox_props, | ||
| transform=ax.transAxes, | ||
| ) | ||
| return ax | ||
93 changes: 93 additions & 0 deletions
93
qiskit_experiments/randomized_benchmarking/interleaved_rb_experiment.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| # This code is part of Qiskit. | ||
| # | ||
| # (C) Copyright IBM 2021. | ||
| # | ||
| # This code is licensed under the Apache License, Version 2.0. You may | ||
| # obtain a copy of this license in the LICENSE.txt file in the root directory | ||
| # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
| # | ||
| # Any modifications or derivative works of this code must retain this | ||
| # copyright notice, and modified files need to carry a notice indicating | ||
| # that they have been altered from the originals. | ||
| """ | ||
| Interleaved RB Experiment class. | ||
| """ | ||
| from typing import Union, Iterable, Optional, List | ||
|
|
||
| from numpy.random import Generator | ||
|
|
||
| from qiskit import QuantumCircuit | ||
| from qiskit.circuit import Instruction | ||
| from qiskit.quantum_info import Clifford, random_clifford | ||
|
|
||
| from .rb_experiment import RBExperiment | ||
| from .interleaved_rb_analysis import InterleavedRBAnalysis | ||
|
|
||
|
|
||
| class InterleavedRBExperiment(RBExperiment): | ||
| """Interleaved RB Experiment class""" | ||
|
|
||
| # Analysis class for experiment | ||
| __analysis_class__ = InterleavedRBAnalysis | ||
|
|
||
| def __init__( | ||
| self, | ||
| interleaved_element: Union[QuantumCircuit, Instruction, Clifford], | ||
| qubits: Union[int, Iterable[int]], | ||
| lengths: Iterable[int], | ||
| num_samples: int = 1, | ||
| seed: Optional[Union[int, Generator]] = None, | ||
| full_sampling: bool = False, | ||
| ): | ||
| """Interleaved randomized benchmarking experiment | ||
| Args: | ||
| interleaved_element: the element to interleave, | ||
| given either as a group element or as an instruction/circuit | ||
| qubits: the number of qubits or list of | ||
| physical qubits for the experiment. | ||
| lengths: A list of RB sequences lengths. | ||
| num_samples: number of samples to generate for each | ||
| sequence length | ||
| seed: Seed or generator object for random number | ||
| generation. If None default_rng will be used. | ||
| full_sampling: If True all Cliffords are independently sampled for | ||
| all lengths. If False for sample of lengths longer | ||
| sequences are constructed by appending additional | ||
| Clifford samples to shorter sequences. | ||
| """ | ||
| self._interleaved_element = interleaved_element | ||
| super().__init__(qubits, lengths, num_samples, seed, full_sampling) | ||
|
|
||
| def _sample_circuits(self, lengths, seed=None): | ||
| circuits = [] | ||
| for length in lengths if self._full_sampling else [lengths[-1]]: | ||
| elements = [random_clifford(self.num_qubits, seed=seed) for _ in range(length)] | ||
| element_lengths = [len(elements)] if self._full_sampling else lengths | ||
| std_circuits = self._generate_circuit(elements, element_lengths) | ||
| for circuit in std_circuits: | ||
| circuit.metadata["series"] = 0 | ||
| circuit.metadata["series_name"] = "standard" | ||
| circuits += std_circuits | ||
|
|
||
| int_elements = self._interleave(elements) | ||
| int_elements_lengths = [length * 2 for length in element_lengths] | ||
| int_circuits = self._generate_circuit(int_elements, int_elements_lengths) | ||
| for circuit in int_circuits: | ||
| circuit.metadata["series"] = 1 | ||
| circuit.metadata["series_name"] = "interleaved" | ||
| circuit.metadata["xval"] = circuit.metadata["xval"] // 2 | ||
| circuits += int_circuits | ||
| return circuits | ||
|
|
||
| def _interleave(self, element_list: List) -> List: | ||
| """Interleaving the interleaved element inside the element list | ||
| Args: | ||
| element_list: The list of elements we add the interleaved element to | ||
| Returns: | ||
| The new list with the element interleaved | ||
| """ | ||
| new_element_list = [] | ||
| for element in element_list: | ||
| new_element_list.append(element) | ||
| new_element_list.append(self._interleaved_element) | ||
| return new_element_list |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.