Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions qiskit_experiments/library/calibration/analysis/drag_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -131,14 +149,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
Expand Down
6 changes: 4 additions & 2 deletions qiskit_experiments/test/mock_iq_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__()

Expand Down Expand Up @@ -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."""
Expand Down
7 changes: 3 additions & 4 deletions test/calibration/experiments/test_drag.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down