Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f3abb34
dt units in cr_hamiltonian
yaelbh Nov 9, 2021
e41b979
updated characterization experiments
yaelbh Nov 10, 2021
0230f39
t1 tests
yaelbh Nov 10, 2021
7188ab4
t2ramsey test
yaelbh Nov 10, 2021
96f7722
cr hamiltonian tests
yaelbh Nov 10, 2021
94b706e
Ramsey XY tests
yaelbh Nov 10, 2021
d55b98d
black
yaelbh Nov 10, 2021
8b49959
lint
yaelbh Nov 10, 2021
c492a17
fixed ramsey xy test
yaelbh Nov 10, 2021
22aee48
Hz
yaelbh Nov 11, 2021
3bd7c4a
black
yaelbh Nov 11, 2021
0639f04
lint
yaelbh Nov 11, 2021
86bc3fc
updated t1 tutorial
yaelbh Nov 16, 2021
78d7817
Merge branch 'main' into units
yaelbh Nov 16, 2021
aae1fa1
lint
yaelbh Nov 16, 2021
38b2188
fixed tests
yaelbh Nov 16, 2021
91596ff
t1 tutorial again (nicer execution count)
yaelbh Nov 16, 2021
224e7f0
updated t2 ramsey tutorial
yaelbh Nov 16, 2021
c48acaa
more update to t2ramsey tutorial
yaelbh Nov 16, 2021
66a7373
fixed analysis option in qubit spectro
yaelbh Nov 16, 2021
97a3881
release notes
yaelbh Nov 16, 2021
326a962
Merge branch 'main' into units
yaelbh Nov 17, 2021
ac1f28b
Merge branch 'main' into units
yaelbh Nov 17, 2021
7ed9ab9
Merge branch 'main' into units
yaelbh Nov 21, 2021
cc5dd35
Update qiskit_experiments/library/calibration/rough_frequency.py
yaelbh Nov 21, 2021
c337c64
Update releasenotes/notes/remove-units-78db311686213a58.yaml
yaelbh Nov 21, 2021
d668c81
Merge branch 'main' into units
yaelbh Nov 21, 2021
646ce76
update xval to the true value following transpilation and conversion …
yaelbh Nov 23, 2021
497fef7
round dts
yaelbh Nov 25, 2021
9e0e250
Merge branch 'main' into units
yaelbh Nov 25, 2021
e470850
fixed rotation angle in t2ramsey
yaelbh Nov 28, 2021
b751c0e
bug fix in t2ramsey
yaelbh Dec 1, 2021
f3f472c
Merge branch 'main' into units
yaelbh Dec 8, 2021
6668412
resolved conflict
yaelbh Dec 9, 2021
28bc939
ramsey_xy
yaelbh Dec 9, 2021
ff2684e
transpile options for ramsey xy
yaelbh Dec 9, 2021
519abd6
Merge branch 'main' into units
yaelbh Dec 9, 2021
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
111 changes: 38 additions & 73 deletions docs/tutorials/t1.ipynb

Large diffs are not rendered by default.

234 changes: 38 additions & 196 deletions docs/tutorials/t2ramsey_characterization.ipynb

Large diffs are not rendered by default.

7 changes: 1 addition & 6 deletions qiskit_experiments/library/calibration/frequency_cal.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ def __init__(
calibrations: Calibrations,
backend: Optional[Backend] = None,
delays: Optional[List] = None,
unit: str = "s",
osc_freq: float = 2e6,
auto_update: bool = True,
):
Expand All @@ -47,10 +46,7 @@ def __init__(
qubit: The qubit on which to run the frequency calibration.
calibrations: The calibrations instance with the schedules.
backend: Optional, the backend to run the experiment on.
delays: The list of delays that will be scanned in the experiment.
unit: The unit of the delays. Accepted values are dt, i.e. the
duration of a single sample on the backend, seconds, and sub-units,
e.g. ms, us, ns.
delays: The list of delays that will be scanned in the experiment, in seconds.
osc_freq: A frequency shift in Hz that will be applied by means of
a virtual Z rotation to increase the frequency of the measured oscillation.
auto_update: If set to True, which is the default, then the experiment will
Expand All @@ -61,7 +57,6 @@ def __init__(
qubit,
backend=backend,
delays=delays,
unit=unit,
osc_freq=osc_freq,
cal_parameter_name=calibrations.__drive_freq_parameter__,
auto_update=auto_update,
Expand Down
16 changes: 4 additions & 12 deletions qiskit_experiments/library/calibration/rough_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def __init__(
calibrations: Calibrations,
frequencies: Iterable[float],
backend: Optional[Backend] = None,
unit: str = "Hz",
auto_update: bool = True,
absolute: bool = True,
):
Expand All @@ -47,25 +46,22 @@ def __init__(
qubit: The qubit on which to run spectroscopy.
calibrations: If calibrations is given then running the experiment may update the values
of the frequencies stored in calibrations.
frequencies: The frequencies to scan in the experiment.
frequencies: The frequencies to scan in the experiment, in Hz.
backend: Optional, the backend to run the experiment on.
unit: The unit in which the user specifies the frequencies. Can be one of 'Hz', 'kHz',
'MHz', 'GHz'. Internally, all frequencies will be converted to 'Hz'.
auto_update: If set to True, which is the default, then the experiment will
automatically update the frequency in the calibrations.
absolute: Boolean to specify if the frequencies are absolute or relative to the
qubit frequency in the backend.

Raises:
QiskitError: if there are less than three frequency shifts or if the unit is not known.
QiskitError: if there are less than three frequency shifts.

"""
super().__init__(
calibrations,
qubit,
frequencies,
backend=backend,
unit=unit,
absolute=absolute,
updater=Frequency,
auto_update=auto_update,
Expand All @@ -87,7 +83,6 @@ def __init__(
qubit: int,
calibrations: Calibrations,
frequencies: Iterable[float],
unit: str = "Hz",
auto_update: bool = True,
absolute: bool = True,
):
Expand All @@ -97,23 +92,20 @@ def __init__(
qubit: The qubit on which to run spectroscopy.
calibrations: If calibrations is given then running the experiment may update the values
of the frequencies stored in calibrations.
frequencies: The frequencies to scan in the experiment.
unit: The unit in which the user specifies the frequencies. Can be one of 'Hz', 'kHz',
'MHz', 'GHz'. Internally, all frequencies will be converted to 'Hz'.
frequencies: The frequencies to scan in the experiment, in Hz.
auto_update: If set to True, which is the default, then the experiment will
automatically update the frequency in the calibrations.
absolute: Boolean to specify if the frequencies are absolute or relative to the
qubit frequency in the backend.

Raises:
QiskitError: if there are less than three frequency shifts or if the unit is not known.
QiskitError: if there are less than three frequency shifts.

"""
super().__init__(
calibrations,
qubit,
frequencies,
unit,
absolute,
cal_parameter_name="f12",
updater=Frequency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from typing import List, Union

import numpy as np
from qiskit.utils import apply_prefix

import qiskit_experiments.curve_analysis as curve
import qiskit_experiments.data_processing as dp
Expand Down Expand Up @@ -85,7 +84,7 @@ class CrossResonanceHamiltonianAnalysis(curve.CurveAnalysis):
desc: Offset to the pulse duration. For example, if pulse envelope is
a flat-topped Gaussian, two Gaussian edges may become an offset duration.
init_guess: Computed as :math:`N \sqrt{2 \pi} \sigma` where the :math:`N` is number of
pulses and :math:`\sigma` is Gaussian sigma of riring and falling edges.
pulses and :math:`\sigma` is Gaussian sigma of rising and falling edges.
Note that this implicitly assumes the :py:class:`~qiskit.pulse.library\
.parametric_pulses.GaussianSquare` pulse envelope.
bounds: [0, None]
Expand Down Expand Up @@ -228,25 +227,16 @@ def _t_off_initial_guess(self) -> float:
An initial guess for time offset parameter ``t_off`` in SI units.

Raises:
AnalysisError: When time unit is ``dt`` but the backend doesn't report
the time resolution of waveforms.
AnalysisError: When the backend doesn't report the time resolution of waveforms.
"""
n_pulses = self._extra_metadata().get("n_cr_pulses", 1)
sigma = self._experiment_options().get("sigma", 0)
unit = self._experiment_options().get("unit")

# Convert sigma unit into SI
if unit == "dt":
try:
prefactor = self._backend.configuration().dt
except AttributeError as ex:
raise AnalysisError(
"Backend configuration does not provide time resolution."
) from ex
elif unit != "s":
prefactor = apply_prefix(1.0, unit)
else:
prefactor = 1.0
try:
prefactor = self._backend.configuration().dt
except AttributeError as ex:
raise AnalysisError("Backend configuration does not provide time resolution.") from ex

return np.sqrt(2 * np.pi) * prefactor * sigma * n_pulses

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"""
T1 Analysis class.
"""
from typing import Union, List
from typing import Union

import qiskit_experiments.curve_analysis as curve

Expand All @@ -38,17 +38,6 @@ def _default_options(cls) -> Options:

return options

def _generate_fit_guesses(
self, user_opt: curve.FitOptions
) -> Union[curve.FitOptions, List[curve.FitOptions]]:
"""Apply conversion factor to tau."""
conversion_factor = self._experiment_options()["conversion_factor"]

if user_opt.p0["tau"] is not None:
user_opt.p0["tau"] *= conversion_factor

return super()._generate_fit_guesses(user_opt)

def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]:
"""Algorithmic criteria for whether the fit is good or bad.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"""
T2Ramsey Experiment class.
"""
from typing import Union, List
from typing import Union

from qiskit_experiments.data_processing import DataProcessor, Probability
import qiskit_experiments.curve_analysis as curve
Expand Down Expand Up @@ -46,17 +46,6 @@ def _default_options(cls) -> Options:

return options

def _generate_fit_guesses(
self, user_opt: curve.FitOptions
) -> Union[curve.FitOptions, List[curve.FitOptions]]:
"""Apply conversion factor to tau."""
conversion_factor = self._experiment_options()["conversion_factor"]

if user_opt.p0["tau"] is not None:
user_opt.p0["tau"] *= conversion_factor

return super()._generate_fit_guesses(user_opt)

def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]:
"""Algorithmic criteria for whether the fit is good or bad.

Expand Down
29 changes: 9 additions & 20 deletions qiskit_experiments/library/characterization/cr_hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from qiskit import pulse, circuit, QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.providers import Backend
from qiskit.utils import apply_prefix
from qiskit_experiments.framework import BaseExperiment, Options
from qiskit_experiments.library.characterization.analysis import CrossResonanceHamiltonianAnalysis

Expand Down Expand Up @@ -131,7 +130,6 @@ def __init__(
qubits: Tuple[int, int],
flat_top_widths: Iterable[float],
backend: Optional[Backend] = None,
unit: str = "dt",
**kwargs,
):
"""Create a new experiment.
Expand All @@ -140,10 +138,10 @@ def __init__(
qubits: Two-value tuple of qubit indices on which to run tomography.
The first index stands for the control qubit.
flat_top_widths: The total duration of the square part of cross resonance pulse(s)
to scan. The total pulse duration including Gaussian rising and falling edges
is implicitly computed with experiment parameters ``sigma`` and ``risefall``.
to scan, in units of dt. The total pulse duration including Gaussian rising and
falling edges is implicitly computed with experiment parameters ``sigma`` and
``risefall``.
backend: Optional, the backend to run the experiment on.
unit: The time unit of durations.
kwargs: Pulse parameters. See :meth:`experiment_options` for details.

Raises:
Expand All @@ -156,26 +154,24 @@ def __init__(
"Length of qubits is not 2. Please provide index for control and target qubit."
)

self.set_experiment_options(flat_top_widths=flat_top_widths, unit=unit, **kwargs)
self.set_experiment_options(flat_top_widths=flat_top_widths, **kwargs)

@classmethod
def _default_experiment_options(cls) -> Options:
"""Default experiment options.

Experiment Options:
flat_top_widths (np.ndarray): The total duration of the square part of
cross resonance pulse(s) to scan. This can start from zero and
cross resonance pulse(s) to scan, in units of dt. This can start from zero and
take positive real values representing the durations.
Pulse edge effect is considered as an offset to the durations.
unit (str): Time unit of durations.
amp (complex): Amplitude of the cross resonance tone.
amp_t (complex): Amplitude of the cancellation or rotary drive on target qubit.
sigma (float): Sigma of Gaussian rise and fall edges.
sigma (float): Sigma of Gaussian rise and fall edges, in units of dt.
risefall (float): Ratio of edge durations to sigma.
"""
options = super()._default_experiment_options()
options.flat_top_widths = None
options.unit = "dt"
options.amp = 0.2
options.amp_t = 0.0
options.sigma = 64
Expand Down Expand Up @@ -264,18 +260,12 @@ def circuits(self) -> List[QuantumCircuit]:
AttributeError: When the backend doesn't report the time resolution of waveforms.
"""
opt = self.experiment_options
prefactor = 1.0

try:
dt_factor = self.backend.configuration().dt
except AttributeError as ex:
raise AttributeError("Backend configuration does not provide time resolution.") from ex

if opt.unit != "dt":
if opt.unit != "s":
prefactor *= apply_prefix(1.0, opt.unit)
prefactor /= dt_factor

# Parametrized duration cannot be used because total duration is computed
# on the fly with granularity validation. This validation requires
# duration value that is not a parameter expression.
Expand All @@ -284,7 +274,6 @@ def circuits(self) -> List[QuantumCircuit]:
expr_circs = list()
for flat_top_width in np.asarray(opt.flat_top_widths, dtype=float):

# circuit duration is shown in given units (just for visualization)
cr_gate = circuit.Gate(
"cr_gate",
num_qubits=2,
Expand Down Expand Up @@ -318,7 +307,7 @@ def circuits(self) -> List[QuantumCircuit]:
tomo_circ.metadata = {
"experiment_type": self.experiment_type,
"qubits": self.physical_qubits,
"xval": prefactor * flat_top_width * dt_factor, # in units of sec
"xval": flat_top_width * dt_factor, # in units of sec
"control_state": control_state,
"meas_basis": meas_basis,
}
Expand All @@ -331,8 +320,8 @@ def circuits(self) -> List[QuantumCircuit]:
qubits=self.physical_qubits,
schedule=self._build_cr_schedule(
backend=self.backend,
flat_top_width=prefactor * flat_top_width / self.__n_cr_pulses__,
sigma=prefactor * opt.sigma,
flat_top_width=flat_top_width / self.__n_cr_pulses__,
sigma=opt.sigma,
),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,10 @@ def __init__(
qubit: int,
frequencies: Iterable[float],
backend: Optional[Backend] = None,
unit: str = "Hz",
absolute: bool = True,
):
super().__init__(qubit, frequencies, backend=backend, unit=unit, absolute=absolute)
self.analysis.set_options(result_parameters=[ParameterRepr("freq", "f12", "Hz")])
super().__init__(qubit, frequencies, backend=backend, absolute=absolute)
self.analysis.set_options(result_parameters=[ParameterRepr("freq", "f12")])

def _template_circuit(self, freq_param) -> QuantumCircuit:
"""Return the template quantum circuit."""
Expand Down
14 changes: 3 additions & 11 deletions qiskit_experiments/library/characterization/qubit_spectroscopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from qiskit.exceptions import QiskitError
from qiskit.providers import Backend
from qiskit.qobj.utils import MeasLevel
from qiskit.utils import apply_prefix

from qiskit_experiments.framework import BaseExperiment, Options
from qiskit_experiments.curve_analysis import ResonanceAnalysis
Expand Down Expand Up @@ -87,7 +86,6 @@ def __init__(
qubit: int,
frequencies: Iterable[float],
backend: Optional[Backend] = None,
unit: str = "Hz",
absolute: bool = True,
):
"""
Expand All @@ -101,27 +99,21 @@ def __init__(

Args:
qubit: The qubit on which to run spectroscopy.
frequencies: The frequencies to scan in the experiment.
frequencies: The frequencies to scan in the experiment, in Hz.
backend: Optional, the backend to run the experiment on.
unit: The unit in which the user specifies the frequencies. Can be one of 'Hz', 'kHz',
'MHz', 'GHz'. Internally, all frequencies will be converted to 'Hz'.
absolute: Boolean to specify if the frequencies are absolute or relative to the
qubit frequency in the backend.

Raises:
QiskitError: if there are less than three frequency shifts or if the unit is not known.
QiskitError: if there are less than three frequency shifts.

"""
super().__init__([qubit], analysis=ResonanceAnalysis(), backend=backend)

if len(frequencies) < 3:
raise QiskitError("Spectroscopy requires at least three frequencies.")

if unit == "Hz":
self._frequencies = frequencies
else:
self._frequencies = [apply_prefix(freq, unit) for freq in frequencies]

self._frequencies = frequencies
self._absolute = absolute

if not self._absolute:
Expand Down
Loading