Skip to content

Commit 2ce4ed1

Browse files
Add exponential fitting to RandomizedBenchMarkResult (#6385)
1 parent 321786d commit 2ce4ed1

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

Diff for: cirq-core/cirq/experiments/qubit_characterizations.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from typing import Any, cast, Iterator, List, Optional, Sequence, Tuple, TYPE_CHECKING
1919
import numpy as np
20+
from scipy.optimize import curve_fit
2021

2122
from matplotlib import pyplot as plt
2223

@@ -92,13 +93,44 @@ def plot(self, ax: Optional[plt.Axes] = None, **plot_kwargs: Any) -> plt.Axes:
9293
fig, ax = plt.subplots(1, 1, figsize=(8, 8)) # pragma: no cover
9394
ax = cast(plt.Axes, ax) # pragma: no cover
9495
ax.set_ylim((0.0, 1.0)) # pragma: no cover
95-
ax.plot(self._num_cfds_seq, self._gnd_state_probs, 'ro-', **plot_kwargs)
96+
ax.plot(self._num_cfds_seq, self._gnd_state_probs, 'ro', label='data', **plot_kwargs)
97+
x = np.linspace(self._num_cfds_seq[0], self._num_cfds_seq[-1], 100)
98+
opt_params, _ = self._fit_exponential()
99+
ax.plot(x, opt_params[0] * opt_params[2] ** x + opt_params[1], '--k', label='fit')
100+
ax.legend(loc='upper right')
96101
ax.set_xlabel(r"Number of Cliffords")
97102
ax.set_ylabel('Ground State Probability')
98103
if show_plot:
99104
fig.show()
100105
return ax
101106

107+
def pauli_error(self) -> float:
108+
r"""Returns the Pauli error inferred from randomized benchmarking.
109+
110+
If sequence fidelity $F$ decays with number of gates $m$ as
111+
112+
$$F = A p^m + B,$$
113+
114+
where $0 < p < 1$, then the Pauli error $r_p$ is given by
115+
116+
$$r_p = (1 - 1/d^2) * (1 - p),$$
117+
118+
where $d = 2^N_Q$ is the Hilbert space dimension and $N_Q$ is the number of qubits.
119+
"""
120+
opt_params, _ = self._fit_exponential()
121+
p = opt_params[2]
122+
return (1.0 - 1.0 / 4.0) * (1.0 - p)
123+
124+
def _fit_exponential(self) -> Tuple[np.ndarray, np.ndarray]:
125+
exp_fit = lambda x, A, B, p: A * p**x + B
126+
return curve_fit(
127+
f=exp_fit,
128+
xdata=self._num_cfds_seq,
129+
ydata=self._gnd_state_probs,
130+
p0=[0.5, 0.5, 1.0 - 1e-3],
131+
bounds=([0, 0.25, 0], [0.5, 0.75, 1]),
132+
)
133+
102134

103135
class TomographyResult:
104136
"""Results from a state tomography experiment."""

Diff for: cirq-core/cirq/experiments/qubit_characterizations_test.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,11 @@ def test_single_qubit_randomized_benchmarking():
8585
# sequences is always unity.
8686
simulator = sim.Simulator()
8787
qubit = GridQubit(0, 0)
88-
num_cfds = range(5, 20, 5)
89-
results = single_qubit_randomized_benchmarking(
90-
simulator, qubit, num_clifford_range=num_cfds, repetitions=100
91-
)
88+
num_cfds = tuple(np.logspace(np.log10(5), 3, 5, dtype=int))
89+
results = single_qubit_randomized_benchmarking(simulator, qubit, num_clifford_range=num_cfds)
9290
g_pops = np.asarray(results.data)[:, 1]
9391
assert np.isclose(np.mean(g_pops), 1.0)
92+
assert np.isclose(results.pauli_error(), 0.0, atol=1e-7) # warning is expected
9493

9594

9695
def test_two_qubit_randomized_benchmarking():

0 commit comments

Comments
 (0)