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
44 changes: 27 additions & 17 deletions qiskit_experiments/library/calibration/fine_amplitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from qiskit import QuantumCircuit
from qiskit.circuit import Gate
from qiskit.circuit.library import XGate, SXGate
from qiskit.providers import Backend
from qiskit.pulse.schedule import ScheduleBlock

Expand Down Expand Up @@ -103,6 +104,8 @@ def _default_experiment_options(cls) -> Options:
Experiment Options:
repetitions (List[int]): A list of the number of times that the gate is repeated.
schedule (ScheduleBlock): The schedule attached to the gate that will be repeated.
gate_type (Type): This is a gate class such as XGate, so that one can obtain a gate
by doing :code:`options.gate_class()`.
normalization (bool): If set to True the DataProcessor will normalized the
measured signal to the interval [0, 1]. Defaults to True.
add_sx (bool): If True then the circuits will start with an sx gate. This is typically
Expand All @@ -115,6 +118,7 @@ def _default_experiment_options(cls) -> Options:
options = super()._default_experiment_options()
options.repetitions = list(range(15))
options.schedule = None
options.gate_type = None
options.normalization = True
options.add_sx = False
options.add_xp_circuit = True
Expand Down Expand Up @@ -197,26 +201,26 @@ def circuits(self, backend: Optional[Backend] = None) -> List[QuantumCircuit]:
"""

# Get the schedule and check assumptions.
schedule = self.experiment_options.get("schedule", None)
schedule = self.experiment_options.schedule

if schedule is None:
raise CalibrationError("No schedule set for fine amplitude calibration.")
gate = self.experiment_options.gate_type()
else:
gate = Gate(name=schedule.name, num_qubits=1, params=[])

if self.physical_qubits[0] not in set(ch.index for ch in schedule.channels):
raise CalibrationError(
f"User provided schedule {schedule.name} does not contain a channel "
"for the qubit on which to run the fine amplitude calibration."
)
if self.physical_qubits[0] not in set(ch.index for ch in schedule.channels):
raise CalibrationError(
f"User provided schedule {schedule.name} does not contain a channel "
"for the qubit on which to run the fine amplitude calibration."
)

if len(schedule.parameters) > 0:
raise CalibrationError(
"All parameters in a fine amplitude calibration schedule must be bound. "
f"Unbound parameters: {schedule.parameters}"
)
if len(schedule.parameters) > 0:
raise CalibrationError(
"All parameters in a fine amplitude calibration schedule must be bound. "
f"Unbound parameters: {schedule.parameters}"
)

# Prepare the circuits.
gate = Gate(name=schedule.name, num_qubits=1, params=[])

repetitions = self.experiment_options.get("repetitions")

circuits = []
Expand All @@ -241,7 +245,7 @@ def circuits(self, backend: Optional[Backend] = None) -> List[QuantumCircuit]:

circuit.metadata = {
"experiment_type": self._type,
"qubits": (self.physical_qubits[0],),
"qubits": self.physical_qubits,
Comment thread
wshanks marked this conversation as resolved.
"xval": (np.pi - phase_offset) / angle_per_gate,
"unit": "gate number",
}
Expand All @@ -255,11 +259,13 @@ def circuits(self, backend: Optional[Backend] = None) -> List[QuantumCircuit]:
circuit.append(gate, (0,))

circuit.measure_all()
circuit.add_calibration(gate, (self.physical_qubits[0],), schedule, params=[])

if schedule is not None:
circuit.add_calibration(gate, self.physical_qubits, schedule, params=[])

circuit.metadata = {
"experiment_type": self._type,
"qubits": (self.physical_qubits[0],),
"qubits": self.physical_qubits,
"xval": repetition,
"unit": "gate number",
}
Expand All @@ -283,13 +289,15 @@ def _default_experiment_options(cls) -> Options:
r"""Default values for the fine amplitude experiment.

Experiment Options:
gate_type (Type): FineXAmplitude calibrates an XGate.
add_sx (bool): This option is True by default when calibrating gates with a target
angle per gate of :math:`\pi` as this increases the sensitivity of the
experiment.
add_xp_circuit (bool): This option is True by default when calibrating gates with
a target angle per gate of :math:`\pi`.
"""
options = super()._default_experiment_options()
options.gate_type = XGate
options.add_sx = True
options.add_xp_circuit = True

Expand Down Expand Up @@ -319,6 +327,7 @@ def _default_experiment_options(cls) -> Options:
r"""Default values for the fine amplitude experiment.

Experiment Options:
gate_type (Type): FineSXAmplitude calibrates an SXGate.
add_sx (bool): This option is False by default when calibrating gates with a target
angle per gate of :math:`\pi/2` as this increases the sensitivity of the
experiment.
Expand All @@ -330,6 +339,7 @@ def _default_experiment_options(cls) -> Options:
plays the same role as including a circuit with an X gate.
"""
options = super()._default_experiment_options()
options.gate_type = SXGate
options.add_sx = False
options.add_xp_circuit = False
options.repetitions = [1, 2, 3, 5, 7, 9, 11, 13, 15, 17, 21, 23, 25]
Expand Down
45 changes: 38 additions & 7 deletions qiskit_experiments/library/calibration/fine_drag.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from qiskit import QuantumCircuit
from qiskit.circuit import Gate
from qiskit.circuit.library import XGate, SXGate
from qiskit.providers import Backend

from qiskit_experiments.framework import BaseExperiment, Options
Expand All @@ -26,7 +27,7 @@


class FineDrag(BaseExperiment):
r"""Fine DRAG Calibration experiment.
r"""Fine DRAG experiment.

# section: overview

Expand Down Expand Up @@ -143,12 +144,13 @@ def _default_experiment_options(cls) -> Options:
repetitions (List[int]): A list of the number of times that Rp - Rm gate sequence
is repeated.
schedule (ScheduleBlock): The schedule for the plus rotation.
normalization (bool): If set to True the DataProcessor will normalized the
measured signal to the interval [0, 1]. Defaults to True.
gate_type (Type[Gate]): This is a gate class such as XGate, so that one can obtain a gate
by doing :code:`options.gate_type()`.
"""
options = super()._default_experiment_options()
options.repetitions = list(range(20))
options.schedule = None
options.gate_type = None

return options

Expand Down Expand Up @@ -195,21 +197,26 @@ def circuits(self, backend: Optional[Backend] = None) -> List[QuantumCircuit]:
"""
schedule, circuits = self.experiment_options.schedule, []

drag_gate = Gate(name=schedule.name, num_qubits=1, params=[])
if schedule is None:
gate = self.experiment_options.gate_type()
else:
gate = Gate(name=schedule.name, num_qubits=1, params=[])

for repetition in self.experiment_options.repetitions:
circuit = self._pre_circuit()

for _ in range(repetition):
circuit.append(drag_gate, (0,))
circuit.append(gate, (0,))
circuit.rz(np.pi, 0)
circuit.append(drag_gate, (0,))
circuit.append(gate, (0,))
circuit.rz(np.pi, 0)

circuit.compose(self._post_circuit(), inplace=True)

circuit.measure_all()
circuit.add_calibration(schedule.name, self._physical_qubits, schedule, params=[])

if schedule is not None:
circuit.add_calibration(schedule.name, self._physical_qubits, schedule, params=[])

circuit.metadata = {
"experiment_type": self._type,
Expand All @@ -230,6 +237,18 @@ class FineXDrag(FineDrag):
qiskit_experiments.library.calibration.fine_drag.FineDrag
"""

@classmethod
def _default_experiment_options(cls) -> Options:
r"""Default values for the FineXDrag experiment.

Experiment Options:
gate_type (Type): FineXDrag calibrates an XGate.
"""
options = super()._default_experiment_options()
options.gate_type = XGate

return options

@staticmethod
def _pre_circuit() -> QuantumCircuit:
"""Return the quantum circuit done before the Rp - Rz - Rp - Rz gates."""
Expand All @@ -243,6 +262,18 @@ class FineSXDrag(FineDrag):
qiskit_experiments.library.calibration.fine_drag.FineDrag
"""

@classmethod
def _default_experiment_options(cls) -> Options:
r"""Default values for the FineSXDrag experiment.

Experiment Options:
gate_type (Type): FineSXDrag calibrates an SXGate.
"""
options = super()._default_experiment_options()
options.gate_type = SXGate

return options

@staticmethod
def _pre_circuit() -> QuantumCircuit:
"""Return the quantum circuit with an sx gate before the Rp - Rz - Rp - Rz gates."""
Expand Down
10 changes: 5 additions & 5 deletions qiskit_experiments/test/mock_iq_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,13 @@ def _compute_probability(self, circuit: QuantumCircuit) -> float:
"""Return the probability of being in the excited state."""

n_ops = circuit.count_ops().get(self._gate_name, 0)
n_sx_ops = circuit.count_ops().get("sx", 0)
n_x_ops = circuit.count_ops().get("x", 0)

angle = n_ops * (self._angle_per_gate + self.angle_error)

angle += np.pi / 2 * n_sx_ops
angle += np.pi * n_x_ops
if self._gate_name != "sx":
angle += np.pi / 2 * circuit.count_ops().get("sx", 0)

if self._gate_name != "x":
angle += np.pi * circuit.count_ops().get("x", 0)

return np.sin(angle / 2) ** 2

Expand Down
21 changes: 21 additions & 0 deletions test/calibration/experiments/test_fine_amplitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import numpy as np

from qiskit.circuit.library import XGate, SXGate
from qiskit.test import QiskitTestCase
from qiskit.pulse import DriveChannel, Drag
import qiskit.pulse as pulse
Expand Down Expand Up @@ -140,6 +141,7 @@ def test_fine_x_amp(self):
self.assertTrue(exp.experiment_options.add_xp_circuit)
self.assertEqual(exp.analysis_options.angle_per_gate, np.pi)
self.assertEqual(exp.analysis_options.phase_offset, np.pi / 2)
self.assertEqual(exp.experiment_options.gate_type, XGate)

def test_fine_sx_amp(self):
"""Test the fine SX amplitude."""
Expand All @@ -153,3 +155,22 @@ def test_fine_sx_amp(self):
self.assertEqual(exp.experiment_options.repetitions, expected)
self.assertEqual(exp.analysis_options.angle_per_gate, np.pi / 2)
self.assertEqual(exp.analysis_options.phase_offset, 0)
self.assertEqual(exp.experiment_options.gate_type, SXGate)

def test_end_to_end_no_schedule(self):
"""Test the experiment end to end."""

amp_cal = FineXAmplitude(0)
amp_cal.set_analysis_options(number_guesses=11)

backend = MockFineAmp(-np.pi * 0.07, np.pi, "x")

expdata = amp_cal.run(backend).block_for_results()
result = expdata.analysis_results(1)
d_theta = result.value.value

tol = 0.04

self.assertTrue(abs(d_theta - backend.angle_error) < tol)
self.assertEqual(result.quality, "good")
self.assertIsNone(amp_cal.experiment_options.schedule)
9 changes: 8 additions & 1 deletion test/calibration/experiments/test_fine_drag.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from qiskit.test.mock import FakeArmonk
import qiskit.pulse as pulse

from qiskit_experiments.library import FineDrag
from qiskit_experiments.library import FineDrag, FineXDrag
from qiskit_experiments.test.mock_iq_backend import DragBackend


Expand Down Expand Up @@ -64,3 +64,10 @@ def test_end_to_end(self):
exp_data = drag.run(FineDragTestBackend()).block_for_results()

self.assertEqual(exp_data.analysis_results(0).quality, "good")

def test_end_to_end_no_schedule(self):
"""Test that we can run without a schedule."""

exp_data = FineXDrag(0).run(FineDragTestBackend()).block_for_results()

self.assertEqual(exp_data.analysis_results(0).quality, "good")