From cd6d64f301702d7e187afeeda911fc8a3b247a91 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Fri, 22 Oct 2021 14:15:59 +0200 Subject: [PATCH 1/3] * Exposed seed in mock iq backend. * Changed default bounds and initial p0 guess in drag analysis. --- .../library/calibration/analysis/drag_analysis.py | 4 ++-- qiskit_experiments/test/mock_iq_backend.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/qiskit_experiments/library/calibration/analysis/drag_analysis.py b/qiskit_experiments/library/calibration/analysis/drag_analysis.py index ec28125e7b..e8264e9306 100644 --- a/qiskit_experiments/library/calibration/analysis/drag_analysis.py +++ b/qiskit_experiments/library/calibration/analysis/drag_analysis.py @@ -131,14 +131,14 @@ def _generate_fit_guesses( freq_bound = max(10 / user_opt.p0["freq0"], max(x_data)) user_opt.bounds.set_if_empty( - amp=(-2 * max_abs_y, 2 * max_abs_y), + amp=(-2 * max_abs_y, 0), freq0=(0, np.inf), freq1=(0, np.inf), freq2=(0, np.inf), beta=(-freq_bound, freq_bound), base=(-max_abs_y, max_abs_y), ) - user_opt.p0.set_if_empty(amp=0.5, base=0.5) + user_opt.p0.set_if_empty(amp=-0.5, base=0.5) # Drag curves can sometimes be very flat, i.e. averages of y-data # and min-max do not always make good initial guesses. We therefore add diff --git a/qiskit_experiments/test/mock_iq_backend.py b/qiskit_experiments/test/mock_iq_backend.py index 695d9b0fc0..c142880a42 100644 --- a/qiskit_experiments/test/mock_iq_backend.py +++ b/qiskit_experiments/test/mock_iq_backend.py @@ -32,13 +32,14 @@ def __init__( self, iq_cluster_centers: Tuple[float, float, float, float] = (1.0, 1.0, -1.0, -1.0), iq_cluster_width: float = 1.0, + rng_seed: int = 0, ): """ Initialize the backend. """ self._iq_cluster_centers = iq_cluster_centers self._iq_cluster_width = iq_cluster_width - self._rng = np.random.default_rng(0) + self._rng = np.random.default_rng(rng_seed) super().__init__() @@ -137,13 +138,14 @@ def __init__( error: float = 0.03, ideal_beta=2.0, gate_name: str = "Rp", + rng_seed: int = 0, ): """Initialize the rabi backend.""" self._error = error self._gate_name = gate_name self.ideal_beta = ideal_beta - super().__init__(iq_cluster_centers, iq_cluster_width) + super().__init__(iq_cluster_centers, iq_cluster_width, rng_seed=rng_seed) def _compute_probability(self, circuit: QuantumCircuit) -> float: """Returns the probability based on the beta, number of gates, and leakage.""" From 73de57c8e33cbfabb0f5794d4fa997801dc95313 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Fri, 22 Oct 2021 14:50:26 +0200 Subject: [PATCH 2/3] * Fix tests. --- test/calibration/experiments/test_drag.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/calibration/experiments/test_drag.py b/test/calibration/experiments/test_drag.py index e2232a41af..bd6ffa1749 100644 --- a/test/calibration/experiments/test_drag.py +++ b/test/calibration/experiments/test_drag.py @@ -55,19 +55,18 @@ def test_end_to_end(self): self.assertTrue(abs(result.value.value - backend.ideal_beta) < self.test_tol) self.assertEqual(result.quality, "good") - # Small leakage will make the curves very flat. - backend = DragBackend(error=0.005, gate_name="xp") + # Small leakage will make the curves very flat, in this case one should + # rather increase beta. + backend = DragBackend(error=0.0051, gate_name="xp") drag = DragCal(0) drag.set_analysis_options(p0={"beta": 1.2}) drag.set_experiment_options(schedule=self.x_plus) - drag.set_run_options(meas_level=MeasLevel.KERNELED, meas_return="avg") exp_data = drag.run(backend).block_for_results() result = exp_data.analysis_results(1) meas_level = exp_data.metadata["job_metadata"][-1]["run_options"]["meas_level"] - self.assertEqual(meas_level, MeasLevel.KERNELED) self.assertTrue(abs(result.value.value - backend.ideal_beta) < self.test_tol) self.assertEqual(result.quality, "good") From 8d981b488db5bc48acfe5cf07e7d7119bde6b3b2 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Fri, 22 Oct 2021 15:16:20 +0200 Subject: [PATCH 3/3] * Improve doc and black. --- .../calibration/analysis/drag_analysis.py | 20 ++++++++++++++++++- test/calibration/experiments/test_drag.py | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/qiskit_experiments/library/calibration/analysis/drag_analysis.py b/qiskit_experiments/library/calibration/analysis/drag_analysis.py index e8264e9306..69b151b00d 100644 --- a/qiskit_experiments/library/calibration/analysis/drag_analysis.py +++ b/qiskit_experiments/library/calibration/analysis/drag_analysis.py @@ -32,7 +32,25 @@ class DragCalAnalysis(curve.CurveAnalysis): .. math:: - y = {\rm amp} \cos\left(2 \pi\cdot {\rm freq}_i\cdot x - 2 \pi \beta\right) + {\rm base} + y_i = {\rm amp} \cos\left(2 \pi\cdot {\rm freq}_i\cdot x - 2 \pi \beta\right) + {\rm base} + + Note that the aim of the Drag calibration is to find the :math:`\beta` that minimizes the + phase shifts. This implies that the optimal :math:`\beta` occurs when all three :math:`y` + curves are minimum, i.e. they produce the ground state. Therefore, + + .. math:: + + y_i = 0 \quad \Longrightarrow \quad -{\rm amp} \cos(2 \pi\cdot X_i) = {\rm base} + + Here, we abbreviated :math:`{\rm freq}_i\cdot x - \beta` by :math:`X_i`. + For a signal between 0 and 1 the :math:`{\rm base}` will typically fit to 0.5. However, the + equation has an ambiguity if the amplitude is not properly bounded. Indeed, + + - if :math:`{\rm amp} < 0` then we require :math:`2 \pi\cdot X_i = 0` mod :math:`2\pi`, and + - if :math:`{\rm amp} > 0` then we require :math:`2 \pi\cdot X_i = \pi` mod :math:`2\pi`. + + This will result in an ambiguity in :math:`\beta` which we avoid by bounding the amplitude + from above by 0. # section: fit_parameters defpar \rm amp: diff --git a/test/calibration/experiments/test_drag.py b/test/calibration/experiments/test_drag.py index bd6ffa1749..4e182f9f8a 100644 --- a/test/calibration/experiments/test_drag.py +++ b/test/calibration/experiments/test_drag.py @@ -56,7 +56,7 @@ def test_end_to_end(self): self.assertEqual(result.quality, "good") # Small leakage will make the curves very flat, in this case one should - # rather increase beta. + # rather increase beta. backend = DragBackend(error=0.0051, gate_name="xp") drag = DragCal(0)