mirror of https://github.com/Qiskit/qiskit.git
Begin deprecation cycle of the discrete pulse library (#10222)
* Add SymbolicPulse counterparts to the discrete library, and start deprecation process. * Typo fix * Release notes styling * Docs and style corrections * autosummary update to avoid name clashes * Remove deprecation section from release notes * Minor changes to Square()
This commit is contained in:
parent
df5d413d78
commit
8a8609f93a
13
docs/conf.py
13
docs/conf.py
|
@ -68,7 +68,7 @@ intersphinx_mapping = {
|
|||
"rustworkx": ("https://qiskit.org/ecosystem/rustworkx/", None),
|
||||
"qiskit-ibm-runtime": ("https://qiskit.org/ecosystem/ibm-runtime/", None),
|
||||
"qiskit-aer": ("https://qiskit.org/ecosystem/aer/", None),
|
||||
"numpy": ("https://numpy.org/doc/stable/", None)
|
||||
"numpy": ("https://numpy.org/doc/stable/", None),
|
||||
}
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
@ -112,6 +112,8 @@ autosummary_filename_map = {
|
|||
"qiskit.pulse.library.Sin": "qiskit.pulse.library.Sin_class.rst",
|
||||
"qiskit.pulse.library.Gaussian": "qiskit.pulse.library.Gaussian_class.rst",
|
||||
"qiskit.pulse.library.Drag": "qiskit.pulse.library.Drag_class.rst",
|
||||
"qiskit.pulse.library.Square": "qiskit.pulse.library.Square_fun.rst",
|
||||
"qiskit.pulse.library.Sech": "qiskit.pulse.library.Sech_fun.rst",
|
||||
}
|
||||
|
||||
autoclass_content = "both"
|
||||
|
@ -119,10 +121,15 @@ autoclass_content = "both"
|
|||
|
||||
# -- Options for Doctest --------------------------------------------------------
|
||||
|
||||
doctest_default_flags = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.IGNORE_EXCEPTION_DETAIL | doctest.DONT_ACCEPT_TRUE_FOR_1
|
||||
doctest_default_flags = (
|
||||
doctest.ELLIPSIS
|
||||
| doctest.NORMALIZE_WHITESPACE
|
||||
| doctest.IGNORE_EXCEPTION_DETAIL
|
||||
| doctest.DONT_ACCEPT_TRUE_FOR_1
|
||||
)
|
||||
|
||||
# Leaving this string empty disables testing of doctest blocks from docstrings.
|
||||
# Doctest blocks are structures like this one:
|
||||
# >> code
|
||||
# output
|
||||
doctest_test_doctest_blocks = ""
|
||||
doctest_test_doctest_blocks = ""
|
||||
|
|
|
@ -147,6 +147,10 @@ from qiskit.pulse.library import (
|
|||
Cos,
|
||||
Sawtooth,
|
||||
Triangle,
|
||||
Square,
|
||||
GaussianDeriv,
|
||||
Sech,
|
||||
SechDeriv,
|
||||
ParametricPulse,
|
||||
SymbolicPulse,
|
||||
ScalableSymbolicPulse,
|
||||
|
|
|
@ -89,10 +89,14 @@ Parametric Pulse Representation
|
|||
GaussianSquare
|
||||
GaussianSquareDrag
|
||||
gaussian_square_echo
|
||||
GaussianDeriv
|
||||
Sin
|
||||
Cos
|
||||
Sawtooth
|
||||
Triangle
|
||||
Square
|
||||
Sech
|
||||
SechDeriv
|
||||
|
||||
"""
|
||||
|
||||
|
@ -119,12 +123,16 @@ from .symbolic_pulses import (
|
|||
GaussianSquare,
|
||||
GaussianSquareDrag,
|
||||
gaussian_square_echo,
|
||||
GaussianDeriv,
|
||||
Drag,
|
||||
Constant,
|
||||
Sin,
|
||||
Cos,
|
||||
Sawtooth,
|
||||
Triangle,
|
||||
Square,
|
||||
Sech,
|
||||
SechDeriv,
|
||||
)
|
||||
from .pulse import Pulse
|
||||
from .waveform import Waveform
|
||||
|
|
|
@ -222,7 +222,7 @@ def gaussian_deriv(
|
|||
rescale_amp=rescale_amp,
|
||||
ret_x=True,
|
||||
)
|
||||
gauss_deriv = -x / sigma * gauss
|
||||
gauss_deriv = -x / sigma * gauss # Note that x is shifted and normalized by sigma
|
||||
if ret_gaussian:
|
||||
return gauss_deriv, gauss
|
||||
return gauss_deriv
|
||||
|
|
|
@ -17,6 +17,7 @@ Note the sampling strategy use for all discrete pulses is ``midpoint``.
|
|||
"""
|
||||
from typing import Optional
|
||||
|
||||
from qiskit.utils.deprecation import deprecate_func
|
||||
from ..exceptions import PulseError
|
||||
from .waveform import Waveform
|
||||
from . import continuous
|
||||
|
@ -26,6 +27,16 @@ from . import samplers
|
|||
_sampled_constant_pulse = samplers.midpoint(continuous.constant)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including constant() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Constant(...).get_waveform(). "
|
||||
" Note that complex value support for the `amp` parameter is pending deprecation"
|
||||
" in the SymbolicPulse library. It is therefore recommended to use two float values"
|
||||
" for (`amp`, `angle`) instead of complex `amp`",
|
||||
pending=True,
|
||||
)
|
||||
def constant(duration: int, amp: complex, name: Optional[str] = None) -> Waveform:
|
||||
r"""Generates constant-sampled :class:`~qiskit.pulse.library.Waveform`.
|
||||
|
||||
|
@ -46,6 +57,13 @@ def constant(duration: int, amp: complex, name: Optional[str] = None) -> Wavefor
|
|||
_sampled_zero_pulse = samplers.midpoint(continuous.zero)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including zero() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Constant(amp=0,...).get_waveform().",
|
||||
pending=True,
|
||||
)
|
||||
def zero(duration: int, name: Optional[str] = None) -> Waveform:
|
||||
"""Generates zero-sampled :class:`~qiskit.pulse.library.Waveform`.
|
||||
|
||||
|
@ -65,6 +83,15 @@ def zero(duration: int, name: Optional[str] = None) -> Waveform:
|
|||
_sampled_square_pulse = samplers.midpoint(continuous.square)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including square() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Square(...).get_waveform()."
|
||||
" Note that pulse.Square() does not support complex values for `amp`,"
|
||||
" and that the phase is defined differently. See documentation.",
|
||||
pending=True,
|
||||
)
|
||||
def square(
|
||||
duration: int, amp: complex, freq: float = None, phase: float = 0, name: Optional[str] = None
|
||||
) -> Waveform:
|
||||
|
@ -97,6 +124,17 @@ def square(
|
|||
_sampled_sawtooth_pulse = samplers.midpoint(continuous.sawtooth)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including sawtooth() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Sawtooth(...).get_waveform()."
|
||||
" Note that pulse.Sawtooth() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`)."
|
||||
" Also note that the phase is defined differently, such that 2*pi phase"
|
||||
" shifts by a full cycle.",
|
||||
pending=True,
|
||||
)
|
||||
def sawtooth(
|
||||
duration: int, amp: complex, freq: float = None, phase: float = 0, name: Optional[str] = None
|
||||
) -> Waveform:
|
||||
|
@ -143,6 +181,15 @@ def sawtooth(
|
|||
_sampled_triangle_pulse = samplers.midpoint(continuous.triangle)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including triangle() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Triangle(...).get_waveform()."
|
||||
" Note that pulse.Triangle() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`).",
|
||||
pending=True,
|
||||
)
|
||||
def triangle(
|
||||
duration: int, amp: complex, freq: float = None, phase: float = 0, name: Optional[str] = None
|
||||
) -> Waveform:
|
||||
|
@ -189,6 +236,15 @@ def triangle(
|
|||
_sampled_cos_pulse = samplers.midpoint(continuous.cos)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including cos() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Cos(...).get_waveform()."
|
||||
" Note that pulse.Cos() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`).",
|
||||
pending=True,
|
||||
)
|
||||
def cos(
|
||||
duration: int, amp: complex, freq: float = None, phase: float = 0, name: Optional[str] = None
|
||||
) -> Waveform:
|
||||
|
@ -218,6 +274,15 @@ def cos(
|
|||
_sampled_sin_pulse = samplers.midpoint(continuous.sin)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including sin() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Sin(...).get_waveform()."
|
||||
" Note that pulse.Sin() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`).",
|
||||
pending=True,
|
||||
)
|
||||
def sin(
|
||||
duration: int, amp: complex, freq: float = None, phase: float = 0, name: Optional[str] = None
|
||||
) -> Waveform:
|
||||
|
@ -247,6 +312,16 @@ def sin(
|
|||
_sampled_gaussian_pulse = samplers.midpoint(continuous.gaussian)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including gaussian() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Gaussian(...).get_waveform()."
|
||||
" Note that complex value support for the `amp` parameter is pending deprecation"
|
||||
" in the SymbolicPulse library. It is therefore recommended to use two float values"
|
||||
" for (`amp`, `angle`) instead of complex `amp`",
|
||||
pending=True,
|
||||
)
|
||||
def gaussian(
|
||||
duration: int, amp: complex, sigma: float, name: Optional[str] = None, zero_ends: bool = True
|
||||
) -> Waveform:
|
||||
|
@ -291,6 +366,15 @@ def gaussian(
|
|||
_sampled_gaussian_deriv_pulse = samplers.midpoint(continuous.gaussian_deriv)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including gaussian_deriv() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.GaussianDeriv(...).get_waveform()."
|
||||
" Note that pulse.GaussianDeriv() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`).",
|
||||
pending=True,
|
||||
)
|
||||
def gaussian_deriv(
|
||||
duration: int, amp: complex, sigma: float, name: Optional[str] = None
|
||||
) -> Waveform:
|
||||
|
@ -301,7 +385,8 @@ def gaussian_deriv(
|
|||
|
||||
.. math::
|
||||
|
||||
f(x) = A\frac{(x - \mu)}{\sigma^2}\exp\left(\left(\frac{x - \mu}{2\sigma}\right)^2 \right)
|
||||
f(x) = -A\frac{(x - \mu)}{\sigma^2}\exp
|
||||
\left(-\frac{1}{2}\left(\frac{x - \mu}{\sigma}\right)^2 \right)
|
||||
|
||||
i.e. the derivative of the Gaussian function, with center :math:`\mu=` ``duration/2``.
|
||||
|
||||
|
@ -318,6 +403,15 @@ def gaussian_deriv(
|
|||
_sampled_sech_pulse = samplers.midpoint(continuous.sech)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including sech() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Sech(...).get_waveform()."
|
||||
" Note that pulse.Sech() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`).",
|
||||
pending=True,
|
||||
)
|
||||
def sech(
|
||||
duration: int, amp: complex, sigma: float, name: str = None, zero_ends: bool = True
|
||||
) -> Waveform:
|
||||
|
@ -360,6 +454,15 @@ def sech(
|
|||
_sampled_sech_deriv_pulse = samplers.midpoint(continuous.sech_deriv)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including sech_deriv() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.SechDeriv(...).get_waveform()."
|
||||
" Note that pulse.SechDeriv() does not support complex values for `amp`."
|
||||
" Instead, use two float values for (`amp`, `angle`).",
|
||||
pending=True,
|
||||
)
|
||||
def sech_deriv(duration: int, amp: complex, sigma: float, name: str = None) -> Waveform:
|
||||
r"""Generates unnormalized sech derivative :class:`~qiskit.pulse.library.Waveform`.
|
||||
|
||||
|
@ -385,6 +488,16 @@ def sech_deriv(duration: int, amp: complex, sigma: float, name: str = None) -> W
|
|||
_sampled_gaussian_square_pulse = samplers.midpoint(continuous.gaussian_square)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including gaussian_square() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.GaussianSquare(...).get_waveform()."
|
||||
" Note that complex value support for the `amp` parameter is pending deprecation"
|
||||
" in the SymbolicPulse library. It is therefore recommended to use two float values"
|
||||
" for (`amp`, `angle`) instead of complex `amp`",
|
||||
pending=True,
|
||||
)
|
||||
def gaussian_square(
|
||||
duration: int,
|
||||
amp: complex,
|
||||
|
@ -451,6 +564,16 @@ def gaussian_square(
|
|||
_sampled_drag_pulse = samplers.midpoint(continuous.drag)
|
||||
|
||||
|
||||
@deprecate_func(
|
||||
since="0.25.0",
|
||||
additional_msg="The discrete pulses library, including drag() is pending deprecation."
|
||||
" Instead, use the SymbolicPulse library to create the waveform with"
|
||||
" pulse.Drag(...).get_waveform()."
|
||||
" Note that complex value support for the `amp` parameter is pending deprecation"
|
||||
" in the SymbolicPulse library. It is therefore recommended to use two float values"
|
||||
" for (`amp`, `angle`) instead of complex `amp`",
|
||||
pending=True,
|
||||
)
|
||||
def drag(
|
||||
duration: int,
|
||||
amp: complex,
|
||||
|
|
|
@ -1085,9 +1085,9 @@ def gaussian_square_echo(
|
|||
The Gaussian Square Echo pulse is composed of three pulses. First, a Gaussian Square pulse
|
||||
:math:`f_{echo}(x)` with amplitude ``amp`` and phase ``angle`` playing for half duration,
|
||||
followed by a second Gaussian Square pulse :math:`-f_{echo}(x)` with opposite amplitude
|
||||
and same phase playing for the rest of the duration. Third a Gaussian Square pulse
|
||||
and same phase playing for the rest of the duration. Third a Gaussian Square pulse
|
||||
:math:`f_{active}(x)` with amplitude ``active_amp`` and phase ``active_angle``
|
||||
playing for the entire duration. The Gaussian Square Echo pulse :math:`g_e()`
|
||||
playing for the entire duration. The Gaussian Square Echo pulse :math:`g_e()`
|
||||
can be written as:
|
||||
|
||||
.. math::
|
||||
|
@ -1099,11 +1099,11 @@ def gaussian_square_echo(
|
|||
& \\frac{\\text{duration}}{2} < x\
|
||||
\\end{cases}\\\\
|
||||
|
||||
One case where this pulse can be used is when implementing a direct CNOT gate with
|
||||
a cross-resonance superconducting qubit architecture. When applying this pulse to
|
||||
the target qubit, the active portion can be used to cancel IX terms from the
|
||||
One case where this pulse can be used is when implementing a direct CNOT gate with
|
||||
a cross-resonance superconducting qubit architecture. When applying this pulse to
|
||||
the target qubit, the active portion can be used to cancel IX terms from the
|
||||
cross-resonance drive while the echo portion can reduce the impact of a static ZZ coupling.
|
||||
|
||||
|
||||
Exactly one of the ``risefall_sigma_ratio`` and ``width`` parameters has to be specified.
|
||||
|
||||
If ``risefall_sigma_ratio`` is not ``None`` and ``width`` is ``None``:
|
||||
|
@ -1122,10 +1122,10 @@ def gaussian_square_echo(
|
|||
|
||||
.. _citation1: https://iopscience.iop.org/article/10.1088/2058-9565/abe519
|
||||
|
||||
.. |citation1| replace:: *Jurcevic, P., Javadi-Abhari, A., Bishop, L. S.,
|
||||
Lauer, I., Bogorin, D. F., Brink, M., Capelluto, L., G{\"u}nl{\"u}k, O.,
|
||||
.. |citation1| replace:: *Jurcevic, P., Javadi-Abhari, A., Bishop, L. S.,
|
||||
Lauer, I., Bogorin, D. F., Brink, M., Capelluto, L., G{\"u}nl{\"u}k, O.,
|
||||
Itoko, T., Kanazawa, N. & others
|
||||
Demonstration of quantum volume 64 on a superconducting quantum
|
||||
Demonstration of quantum volume 64 on a superconducting quantum
|
||||
computing system. (Section V)*
|
||||
Args:
|
||||
duration: Pulse length in terms of the sampling period `dt`.
|
||||
|
@ -1269,6 +1269,72 @@ def gaussian_square_echo(
|
|||
return instance
|
||||
|
||||
|
||||
def GaussianDeriv(
|
||||
duration: Union[int, ParameterExpression],
|
||||
amp: Union[float, ParameterExpression],
|
||||
sigma: Union[float, ParameterExpression],
|
||||
angle: Optional[Union[float, ParameterExpression]] = 0.0,
|
||||
name: Optional[str] = None,
|
||||
limit_amplitude: Optional[bool] = None,
|
||||
) -> ScalableSymbolicPulse:
|
||||
"""An unnormalized Gaussian derivative pulse.
|
||||
|
||||
The Gaussian function is centered around the halfway point of the pulse,
|
||||
and the envelope of the pulse is given by:
|
||||
|
||||
.. math::
|
||||
|
||||
f(x) = -\\text{A}\\frac{x-\\mu}{\\text{sigma}^{2}}\\exp
|
||||
\\left[-\\left(\\frac{x-\\mu}{2\\text{sigma}}\\right)^{2}\\right] , 0 <= x < duration
|
||||
|
||||
where :math:`\\text{A} = \\text{amp} \\times\\exp\\left(i\\times\\text{angle}\\right)`,
|
||||
and :math:`\\mu=\\text{duration}/2`.
|
||||
|
||||
Args:
|
||||
duration: Pulse length in terms of the sampling period `dt`.
|
||||
amp: The magnitude of the amplitude of the pulse
|
||||
(the value of the corresponding Gaussian at the midpoint `duration`/2).
|
||||
sigma: A measure of how wide or narrow the corresponding Gaussian peak is in terms of `dt`;
|
||||
described mathematically in the class docstring.
|
||||
angle: The angle in radians of the complex phase factor uniformly
|
||||
scaling the pulse. Default value 0.
|
||||
name: Display name for this pulse envelope.
|
||||
limit_amplitude: If ``True``, then limit the amplitude of the
|
||||
waveform to 1. The default is ``True`` and the amplitude is constrained to 1.
|
||||
|
||||
Returns:
|
||||
ScalableSymbolicPulse instance.
|
||||
"""
|
||||
parameters = {"sigma": sigma}
|
||||
|
||||
# Prepare symbolic expressions
|
||||
_t, _duration, _amp, _angle, _sigma = sym.symbols("t, duration, amp, angle, sigma")
|
||||
envelope_expr = (
|
||||
-_amp
|
||||
* sym.exp(sym.I * _angle)
|
||||
* ((_t - (_duration / 2)) / _sigma**2)
|
||||
* sym.exp(-(1 / 2) * ((_t - (_duration / 2)) / _sigma) ** 2)
|
||||
)
|
||||
consts_expr = _sigma > 0
|
||||
valid_amp_conditions_expr = sym.Abs(_amp / _sigma) <= sym.exp(1 / 2)
|
||||
|
||||
instance = ScalableSymbolicPulse(
|
||||
pulse_type="GaussianDeriv",
|
||||
duration=duration,
|
||||
amp=amp,
|
||||
angle=angle,
|
||||
parameters=parameters,
|
||||
name=name,
|
||||
limit_amplitude=limit_amplitude,
|
||||
envelope=envelope_expr,
|
||||
constraints=consts_expr,
|
||||
valid_amp_conditions=valid_amp_conditions_expr,
|
||||
)
|
||||
instance.validate_parameters()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class Drag(metaclass=_PulseType):
|
||||
"""The Derivative Removal by Adiabatic Gate (DRAG) pulse is a standard Gaussian pulse
|
||||
with an additional Gaussian derivative component and lifting applied.
|
||||
|
@ -1649,7 +1715,7 @@ def Triangle(
|
|||
name: Optional[str] = None,
|
||||
limit_amplitude: Optional[bool] = None,
|
||||
) -> ScalableSymbolicPulse:
|
||||
"""A triangle pulse.
|
||||
"""A triangle wave pulse.
|
||||
|
||||
The envelope of the pulse is given by:
|
||||
|
||||
|
@ -1709,3 +1775,221 @@ def Triangle(
|
|||
instance.validate_parameters()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def Square(
|
||||
duration: Union[int, ParameterExpression],
|
||||
amp: Union[float, ParameterExpression],
|
||||
phase: Union[float, ParameterExpression],
|
||||
freq: Optional[Union[float, ParameterExpression]] = None,
|
||||
angle: Optional[Union[float, ParameterExpression]] = 0.0,
|
||||
name: Optional[str] = None,
|
||||
limit_amplitude: Optional[bool] = None,
|
||||
) -> ScalableSymbolicPulse:
|
||||
"""A square wave pulse.
|
||||
|
||||
The envelope of the pulse is given by:
|
||||
|
||||
.. math::
|
||||
|
||||
f(x) = \\text{A}\\text{sign}\\left[\\sin
|
||||
\\left(2\\pi x\\times\\text{freq}+\\text{phase}\\right)\\right] , 0 <= x < duration
|
||||
|
||||
where :math:`\\text{A} = \\text{amp} \\times\\exp\\left(i\\times\\text{angle}\\right)`,
|
||||
and :math:`\\text{sign}`
|
||||
is the sign function with the convention :math:`\\text{sign}\\left(0\\right)=1`.
|
||||
|
||||
Args:
|
||||
duration: Pulse length in terms of the sampling period `dt`.
|
||||
amp: The magnitude of the amplitude of the square wave. Wave range is [-`amp`,`amp`].
|
||||
phase: The phase of the square wave (note that this is not equivalent to the angle of
|
||||
the complex amplitude).
|
||||
freq: The frequency of the square wave, in terms of 1 over sampling period.
|
||||
If not provided defaults to a single cycle (i.e :math:'\\frac{1}{\\text{duration}}').
|
||||
The frequency is limited to the range :math:`\\left(0,0.5\\right]` (the Nyquist frequency).
|
||||
angle: The angle in radians of the complex phase factor uniformly
|
||||
scaling the pulse. Default value 0.
|
||||
name: Display name for this pulse envelope.
|
||||
limit_amplitude: If ``True``, then limit the amplitude of the
|
||||
waveform to 1. The default is ``True`` and the amplitude is constrained to 1.
|
||||
|
||||
Returns:
|
||||
ScalableSymbolicPulse instance.
|
||||
"""
|
||||
if freq is None:
|
||||
freq = 1 / duration
|
||||
parameters = {"freq": freq, "phase": phase}
|
||||
|
||||
# Prepare symbolic expressions
|
||||
_t, _duration, _amp, _angle, _freq, _phase = sym.symbols("t, duration, amp, angle, freq, phase")
|
||||
_x = _freq * _t + _phase / (2 * sym.pi)
|
||||
|
||||
envelope_expr = (
|
||||
_amp * sym.exp(sym.I * _angle) * (2 * (2 * sym.floor(_x) - sym.floor(2 * _x)) + 1)
|
||||
)
|
||||
|
||||
consts_expr = sym.And(_freq > 0, _freq < 0.5)
|
||||
|
||||
# This might fail for waves shorter than a single cycle
|
||||
valid_amp_conditions_expr = sym.Abs(_amp) <= 1.0
|
||||
|
||||
instance = ScalableSymbolicPulse(
|
||||
pulse_type="Square",
|
||||
duration=duration,
|
||||
amp=amp,
|
||||
angle=angle,
|
||||
parameters=parameters,
|
||||
name=name,
|
||||
limit_amplitude=limit_amplitude,
|
||||
envelope=envelope_expr,
|
||||
constraints=consts_expr,
|
||||
valid_amp_conditions=valid_amp_conditions_expr,
|
||||
)
|
||||
instance.validate_parameters()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def Sech(
|
||||
duration: Union[int, ParameterExpression],
|
||||
amp: Union[float, ParameterExpression],
|
||||
sigma: Union[float, ParameterExpression],
|
||||
angle: Optional[Union[float, ParameterExpression]] = 0.0,
|
||||
name: Optional[str] = None,
|
||||
zero_ends: Optional[bool] = True,
|
||||
limit_amplitude: Optional[bool] = None,
|
||||
) -> ScalableSymbolicPulse:
|
||||
"""An unnormalized sech pulse.
|
||||
|
||||
The sech function is centered around the halfway point of the pulse,
|
||||
and the envelope of the pulse is given by:
|
||||
|
||||
.. math::
|
||||
|
||||
f(x) = \\text{A}\\text{sech}\\left(
|
||||
\\frac{x-\\mu}{\\text{sigma}}\\right) , 0 <= x < duration
|
||||
|
||||
where :math:`\\text{A} = \\text{amp} \\times\\exp\\left(i\\times\\text{angle}\\right)`,
|
||||
and :math:`\\mu=\\text{duration}/2`.
|
||||
|
||||
If `zero_ends` is set to `True`, the output `y` is modified:
|
||||
.. math::
|
||||
|
||||
y\\left(x\\right) \\mapsto \\text{A}\\frac{y-y^{*}}{\\text{A}-y^{*}},
|
||||
|
||||
where :math:`y^{*}` is the value of :math:`y` at the endpoints (at :math:`x=-1
|
||||
and :math:`x=\\text{duration}+1`). This shifts the endpoints value to zero, while also
|
||||
rescaling to preserve the amplitude at `:math:`\\text{duration}/2``.
|
||||
|
||||
Args:
|
||||
duration: Pulse length in terms of the sampling period `dt`.
|
||||
amp: The magnitude of the amplitude of the pulse (the value at the midpoint `duration`/2).
|
||||
sigma: A measure of how wide or narrow the sech peak is in terms of `dt`;
|
||||
described mathematically in the class docstring.
|
||||
angle: The angle in radians of the complex phase factor uniformly
|
||||
scaling the pulse. Default value 0.
|
||||
name: Display name for this pulse envelope.
|
||||
zero_ends: If True, zeros the ends at x = -1, x = `duration` + 1,
|
||||
but rescales to preserve `amp`. Default value True.
|
||||
limit_amplitude: If ``True``, then limit the amplitude of the
|
||||
waveform to 1. The default is ``True`` and the amplitude is constrained to 1.
|
||||
|
||||
Returns:
|
||||
ScalableSymbolicPulse instance.
|
||||
"""
|
||||
parameters = {"sigma": sigma}
|
||||
|
||||
# Prepare symbolic expressions
|
||||
_t, _duration, _amp, _angle, _sigma = sym.symbols("t, duration, amp, angle, sigma")
|
||||
complex_amp = _amp * sym.exp(sym.I * _angle)
|
||||
envelope_expr = complex_amp * sym.sech((_t - (_duration / 2)) / _sigma)
|
||||
|
||||
if zero_ends:
|
||||
shift_val = complex_amp * sym.sech((-1 - (_duration / 2)) / _sigma)
|
||||
envelope_expr = complex_amp * (envelope_expr - shift_val) / (complex_amp - shift_val)
|
||||
|
||||
consts_expr = _sigma > 0
|
||||
|
||||
valid_amp_conditions_expr = sym.Abs(_amp) <= 1.0
|
||||
|
||||
instance = ScalableSymbolicPulse(
|
||||
pulse_type="Sech",
|
||||
duration=duration,
|
||||
amp=amp,
|
||||
angle=angle,
|
||||
parameters=parameters,
|
||||
name=name,
|
||||
limit_amplitude=limit_amplitude,
|
||||
envelope=envelope_expr,
|
||||
constraints=consts_expr,
|
||||
valid_amp_conditions=valid_amp_conditions_expr,
|
||||
)
|
||||
instance.validate_parameters()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def SechDeriv(
|
||||
duration: Union[int, ParameterExpression],
|
||||
amp: Union[float, ParameterExpression],
|
||||
sigma: Union[float, ParameterExpression],
|
||||
angle: Optional[Union[float, ParameterExpression]] = 0.0,
|
||||
name: Optional[str] = None,
|
||||
limit_amplitude: Optional[bool] = None,
|
||||
) -> ScalableSymbolicPulse:
|
||||
"""An unnormalized sech derivative pulse.
|
||||
|
||||
The sech function is centered around the halfway point of the pulse, and the envelope of the
|
||||
pulse is given by:
|
||||
|
||||
.. math::
|
||||
|
||||
f(x) = \\text{A}\\frac{d}{dx}\\left[\\text{sech}
|
||||
\\left(\\frac{x-\\mu}{\\text{sigma}}\\right)\\right] , 0 <= x < duration
|
||||
|
||||
where :math:`\\text{A} = \\text{amp} \\times\\exp\\left(i\\times\\text{angle}\\right)`,
|
||||
:math:`\\mu=\\text{duration}/2`, and :math:`d/dx` is a derivative with respect to `x`.
|
||||
|
||||
Args:
|
||||
duration: Pulse length in terms of the sampling period `dt`.
|
||||
amp: The magnitude of the amplitude of the pulse (the value of the corresponding sech
|
||||
function at the midpoint `duration`/2).
|
||||
sigma: A measure of how wide or narrow the corresponding sech peak is, in terms of `dt`;
|
||||
described mathematically in the class docstring.
|
||||
angle: The angle in radians of the complex phase factor uniformly
|
||||
scaling the pulse. Default value 0.
|
||||
name: Display name for this pulse envelope.
|
||||
limit_amplitude: If ``True``, then limit the amplitude of the
|
||||
waveform to 1. The default is ``True`` and the amplitude is constrained to 1.
|
||||
|
||||
Returns:
|
||||
ScalableSymbolicPulse instance.
|
||||
"""
|
||||
parameters = {"sigma": sigma}
|
||||
|
||||
# Prepare symbolic expressions
|
||||
_t, _duration, _amp, _angle, _sigma = sym.symbols("t, duration, amp, angle, sigma")
|
||||
time_argument = (_t - (_duration / 2)) / _sigma
|
||||
sech_deriv = -sym.tanh(time_argument) * sym.sech(time_argument) / _sigma
|
||||
|
||||
envelope_expr = _amp * sym.exp(sym.I * _angle) * sech_deriv
|
||||
|
||||
consts_expr = _sigma > 0
|
||||
|
||||
valid_amp_conditions_expr = sym.Abs(_amp) / _sigma <= 2.0
|
||||
|
||||
instance = ScalableSymbolicPulse(
|
||||
pulse_type="SechDeriv",
|
||||
duration=duration,
|
||||
amp=amp,
|
||||
angle=angle,
|
||||
parameters=parameters,
|
||||
name=name,
|
||||
limit_amplitude=limit_amplitude,
|
||||
envelope=envelope_expr,
|
||||
constraints=consts_expr,
|
||||
valid_amp_conditions=valid_amp_conditions_expr,
|
||||
)
|
||||
instance.validate_parameters()
|
||||
|
||||
return instance
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
The :class:`~qiskit.pulse.SymbolicPulse` library was extended. The new pulses in the library are:
|
||||
|
||||
* :func:`~qiskit.pulse.library.GaussianDeriv`
|
||||
* :func:`~qiskit.pulse.library.Sech`
|
||||
* :func:`~qiskit.pulse.library.SechDeriv`
|
||||
* :func:`~qiskit.pulse.library.Square`
|
||||
|
||||
The new functions return a :class:`ScalableSymbolicPulse`, and match the functionality
|
||||
of the corresponding functions in the discrete pulse library, with the exception of
|
||||
`Square()` for which a phase of :math:`2\\pi` shifts by a full cycle (contrary to the
|
||||
discrete `square()` where such a shift was induced by a :math:`\\pi` phase).
|
|
@ -224,3 +224,32 @@ class TestDiscretePulses(QiskitTestCase):
|
|||
drag_pulse = library.drag(duration, amp, sigma, beta=beta)
|
||||
self.assertIsInstance(drag_pulse, Waveform)
|
||||
np.testing.assert_array_almost_equal(drag_pulse.samples, drag_ref)
|
||||
|
||||
def test_pending_deprecation_warnings(self):
|
||||
"""Test that pending deprecation warnings are raised when the discrete library is used."""
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.drag(duration=10, amp=0.5, sigma=0.1, beta=0.1)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.gaussian_square(duration=10, amp=0.5, sigma=0.1, risefall=2, width=6)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.gaussian(duration=10, amp=0.5, sigma=0.1)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.sin(duration=10, amp=0.5)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.cos(duration=10, amp=0.5)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.sawtooth(duration=10, amp=0.5)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.zero(duration=10)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.constant(duration=10, amp=0.5)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.triangle(duration=10, amp=0.5)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.gaussian_deriv(duration=10, amp=0.5, sigma=3)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.sech_deriv(duration=10, amp=0.5, sigma=3)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.sech(duration=10, amp=0.5, sigma=3)
|
||||
with self.assertWarns(PendingDeprecationWarning):
|
||||
library.square(duration=10, amp=0.5)
|
||||
|
|
|
@ -25,18 +25,26 @@ from qiskit.pulse.library import (
|
|||
GaussianSquare,
|
||||
GaussianSquareDrag,
|
||||
gaussian_square_echo,
|
||||
GaussianDeriv,
|
||||
Drag,
|
||||
Sin,
|
||||
Cos,
|
||||
Sawtooth,
|
||||
Triangle,
|
||||
Square,
|
||||
Sech,
|
||||
SechDeriv,
|
||||
gaussian,
|
||||
gaussian_square,
|
||||
gaussian_deriv,
|
||||
drag as pl_drag,
|
||||
sin,
|
||||
cos,
|
||||
triangle,
|
||||
sawtooth,
|
||||
square,
|
||||
sech,
|
||||
sech_deriv,
|
||||
)
|
||||
|
||||
from qiskit.pulse import functional_pulse, PulseError
|
||||
|
@ -138,12 +146,17 @@ class TestParametricPulses(QiskitTestCase):
|
|||
Gaussian(duration=25, sigma=4, amp=0.5j)
|
||||
GaussianSquare(duration=150, amp=0.2, sigma=8, width=140)
|
||||
GaussianSquare(duration=150, amp=0.2, sigma=8, risefall_sigma_ratio=2.5)
|
||||
GaussianDeriv(duration=150, amp=0.2, sigma=8)
|
||||
Constant(duration=150, amp=0.1 + 0.4j)
|
||||
Drag(duration=25, amp=0.2 + 0.3j, sigma=7.8, beta=4)
|
||||
Sin(duration=25, amp=0.5, freq=0.1, phase=0.5, angle=0.5)
|
||||
Cos(duration=30, amp=0.5, freq=0.1, phase=-0.5)
|
||||
Sawtooth(duration=40, amp=0.5, freq=0.2, phase=3.14)
|
||||
Triangle(duration=50, amp=0.5, freq=0.01, phase=0.5)
|
||||
Square(duration=50, amp=0.5, freq=0.01, phase=0.5)
|
||||
Sech(duration=50, amp=0.5, sigma=10)
|
||||
Sech(duration=50, amp=0.5, sigma=10, zero_ends=False)
|
||||
SechDeriv(duration=50, amp=0.5, sigma=10)
|
||||
|
||||
# This test should be removed once deprecation of complex amp is completed.
|
||||
def test_complex_amp_deprecation(self):
|
||||
|
@ -412,7 +425,7 @@ class TestParametricPulses(QiskitTestCase):
|
|||
Sin(duration=duration, amp=amp, freq=5, phase=phase)
|
||||
|
||||
def test_cos_pulse(self):
|
||||
"""Test that Cin sample pulse matches expectations, and parameter validation"""
|
||||
"""Test that Cos sample pulse matches expectations, and parameter validation"""
|
||||
duration = 100
|
||||
amp = 0.5
|
||||
freq = 0.1
|
||||
|
@ -428,6 +441,20 @@ class TestParametricPulses(QiskitTestCase):
|
|||
with self.assertRaises(PulseError):
|
||||
Cos(duration=duration, amp=amp, freq=5, phase=phase)
|
||||
|
||||
def test_square_pulse(self):
|
||||
"""Test that Square sample pulse matches expectations, and parameter validation"""
|
||||
duration = 100
|
||||
amp = 0.5
|
||||
freq = 0.1
|
||||
phase = 0.3
|
||||
square_pulse = Square(duration=duration, amp=amp, freq=freq, phase=phase)
|
||||
square_waveform = square(duration=duration, amp=amp, freq=freq, phase=phase / 2)
|
||||
|
||||
np.testing.assert_almost_equal(square_pulse.get_waveform().samples, square_waveform.samples)
|
||||
|
||||
with self.assertRaises(PulseError):
|
||||
Square(duration=duration, amp=amp, freq=5, phase=phase)
|
||||
|
||||
def test_sawtooth_pulse(self):
|
||||
"""Test that Sawtooth sample pulse matches expectations, and parameter validation"""
|
||||
duration = 100
|
||||
|
@ -449,7 +476,7 @@ class TestParametricPulses(QiskitTestCase):
|
|||
Sawtooth(duration=duration, amp=amp, freq=5, phase=phase)
|
||||
|
||||
def test_triangle_pulse(self):
|
||||
"""Test that Sawtooth sample pulse matches expectations, and parameter validation"""
|
||||
"""Test that Triangle sample pulse matches expectations, and parameter validation"""
|
||||
duration = 100
|
||||
amp = 0.5
|
||||
freq = 0.1
|
||||
|
@ -467,6 +494,51 @@ class TestParametricPulses(QiskitTestCase):
|
|||
with self.assertRaises(PulseError):
|
||||
Triangle(duration=duration, amp=amp, freq=5, phase=phase)
|
||||
|
||||
def test_gaussian_deriv_pulse(self):
|
||||
"""Test that GaussianDeriv sample pulse matches expectations"""
|
||||
duration = 300
|
||||
amp = 0.5
|
||||
sigma = 100
|
||||
gaussian_deriv_pulse = GaussianDeriv(duration=duration, amp=amp, sigma=sigma)
|
||||
gaussian_deriv_waveform = gaussian_deriv(duration=duration, amp=amp, sigma=sigma)
|
||||
np.testing.assert_almost_equal(
|
||||
gaussian_deriv_pulse.get_waveform().samples, gaussian_deriv_waveform.samples
|
||||
)
|
||||
with self.assertRaises(PulseError):
|
||||
Sech(duration=duration, amp=amp, sigma=0)
|
||||
|
||||
def test_sech_pulse(self):
|
||||
"""Test that Sech sample pulse matches expectations, and parameter validation"""
|
||||
duration = 100
|
||||
amp = 0.5
|
||||
sigma = 10
|
||||
# Zero ends = True
|
||||
sech_pulse = Sech(duration=duration, amp=amp, sigma=sigma)
|
||||
sech_waveform = sech(duration=duration, amp=amp, sigma=sigma)
|
||||
np.testing.assert_almost_equal(sech_pulse.get_waveform().samples, sech_waveform.samples)
|
||||
|
||||
# Zero ends = False
|
||||
sech_pulse = Sech(duration=duration, amp=amp, sigma=sigma, zero_ends=False)
|
||||
sech_waveform = sech(duration=duration, amp=amp, sigma=sigma, zero_ends=False)
|
||||
np.testing.assert_almost_equal(sech_pulse.get_waveform().samples, sech_waveform.samples)
|
||||
|
||||
with self.assertRaises(PulseError):
|
||||
Sech(duration=duration, amp=amp, sigma=-5)
|
||||
|
||||
def test_sech_deriv_pulse(self):
|
||||
"""Test that SechDeriv sample pulse matches expectations, and parameter validation"""
|
||||
duration = 100
|
||||
amp = 0.5
|
||||
sigma = 10
|
||||
sech_deriv_pulse = SechDeriv(duration=duration, amp=amp, sigma=sigma)
|
||||
sech_deriv_waveform = sech_deriv(duration=duration, amp=amp, sigma=sigma)
|
||||
np.testing.assert_almost_equal(
|
||||
sech_deriv_pulse.get_waveform().samples, sech_deriv_waveform.samples
|
||||
)
|
||||
|
||||
with self.assertRaises(PulseError):
|
||||
SechDeriv(duration=duration, amp=amp, sigma=-5)
|
||||
|
||||
def test_constant_samples(self):
|
||||
"""Test the constant pulse and its sampled construction."""
|
||||
const = Constant(duration=150, amp=0.1 + 0.4j)
|
||||
|
@ -531,6 +603,32 @@ class TestParametricPulses(QiskitTestCase):
|
|||
self.assertEqual(repr(drag), "Drag(duration=5, sigma=7, beta=1, amp=0.5, angle=0)")
|
||||
const = Constant(duration=150, amp=0.1, angle=0.3)
|
||||
self.assertEqual(repr(const), "Constant(duration=150, amp=0.1, angle=0.3)")
|
||||
sin_pulse = Sin(duration=150, amp=0.1, angle=0.3, freq=0.2, phase=0)
|
||||
self.assertEqual(
|
||||
repr(sin_pulse), "Sin(duration=150, freq=0.2, phase=0, amp=0.1, angle=0.3)"
|
||||
)
|
||||
cos_pulse = Cos(duration=150, amp=0.1, angle=0.3, freq=0.2, phase=0)
|
||||
self.assertEqual(
|
||||
repr(cos_pulse), "Cos(duration=150, freq=0.2, phase=0, amp=0.1, angle=0.3)"
|
||||
)
|
||||
triangle_pulse = Triangle(duration=150, amp=0.1, angle=0.3, freq=0.2, phase=0)
|
||||
self.assertEqual(
|
||||
repr(triangle_pulse), "Triangle(duration=150, freq=0.2, phase=0, amp=0.1, angle=0.3)"
|
||||
)
|
||||
sawtooth_pulse = Sawtooth(duration=150, amp=0.1, angle=0.3, freq=0.2, phase=0)
|
||||
self.assertEqual(
|
||||
repr(sawtooth_pulse), "Sawtooth(duration=150, freq=0.2, phase=0, amp=0.1, angle=0.3)"
|
||||
)
|
||||
sech_pulse = Sech(duration=150, amp=0.1, angle=0.3, sigma=10)
|
||||
self.assertEqual(repr(sech_pulse), "Sech(duration=150, sigma=10, amp=0.1, angle=0.3)")
|
||||
sech_deriv_pulse = SechDeriv(duration=150, amp=0.1, angle=0.3, sigma=10)
|
||||
self.assertEqual(
|
||||
repr(sech_deriv_pulse), "SechDeriv(duration=150, sigma=10, amp=0.1, angle=0.3)"
|
||||
)
|
||||
gaussian_deriv_pulse = GaussianDeriv(duration=150, amp=0.1, angle=0.3, sigma=10)
|
||||
self.assertEqual(
|
||||
repr(gaussian_deriv_pulse), "GaussianDeriv(duration=150, sigma=10, amp=0.1, angle=0.3)"
|
||||
)
|
||||
|
||||
def test_param_validation(self):
|
||||
"""Test that parametric pulse parameters are validated when initialized."""
|
||||
|
@ -727,6 +825,74 @@ class TestParametricPulses(QiskitTestCase):
|
|||
waveform = Triangle(duration=100, amp=1.1, phase=0, limit_amplitude=False)
|
||||
self.assertGreater(np.abs(waveform.amp), 1.0)
|
||||
|
||||
def test_square_limit_amplitude(self):
|
||||
"""Test that the check for amplitude less than or equal to 1 can be disabled."""
|
||||
with self.assertRaises(PulseError):
|
||||
Square(duration=100, amp=1.1, phase=0)
|
||||
|
||||
with patch("qiskit.pulse.library.pulse.Pulse.limit_amplitude", new=False):
|
||||
waveform = Square(duration=100, amp=1.1, phase=0)
|
||||
self.assertGreater(np.abs(waveform.amp), 1.0)
|
||||
|
||||
def test_square_limit_amplitude_per_instance(self):
|
||||
"""Test that the check for amplitude per instance."""
|
||||
with self.assertRaises(PulseError):
|
||||
Square(duration=100, amp=1.1, phase=0)
|
||||
|
||||
waveform = Square(duration=100, amp=1.1, phase=0, limit_amplitude=False)
|
||||
self.assertGreater(np.abs(waveform.amp), 1.0)
|
||||
|
||||
def test_gaussian_deriv_limit_amplitude(self):
|
||||
"""Test that the check for amplitude less than or equal to 1 can be disabled."""
|
||||
with self.assertRaises(PulseError):
|
||||
GaussianDeriv(duration=100, amp=5, sigma=1)
|
||||
|
||||
with patch("qiskit.pulse.library.pulse.Pulse.limit_amplitude", new=False):
|
||||
waveform = GaussianDeriv(duration=100, amp=5, sigma=1)
|
||||
self.assertGreater(np.abs(waveform.amp / waveform.sigma), np.exp(0.5))
|
||||
|
||||
def test_gaussian_deriv_limit_amplitude_per_instance(self):
|
||||
"""Test that the check for amplitude per instance."""
|
||||
with self.assertRaises(PulseError):
|
||||
GaussianDeriv(duration=100, amp=5, sigma=1)
|
||||
|
||||
waveform = GaussianDeriv(duration=100, amp=5, sigma=1, limit_amplitude=False)
|
||||
self.assertGreater(np.abs(waveform.amp / waveform.sigma), np.exp(0.5))
|
||||
|
||||
def test_sech_limit_amplitude(self):
|
||||
"""Test that the check for amplitude less than or equal to 1 can be disabled."""
|
||||
with self.assertRaises(PulseError):
|
||||
Sech(duration=100, amp=5, sigma=1)
|
||||
|
||||
with patch("qiskit.pulse.library.pulse.Pulse.limit_amplitude", new=False):
|
||||
waveform = Sech(duration=100, amp=5, sigma=1)
|
||||
self.assertGreater(np.abs(waveform.amp), 1.0)
|
||||
|
||||
def test_sech_limit_amplitude_per_instance(self):
|
||||
"""Test that the check for amplitude per instance."""
|
||||
with self.assertRaises(PulseError):
|
||||
Sech(duration=100, amp=5, sigma=1)
|
||||
|
||||
waveform = Sech(duration=100, amp=5, sigma=1, limit_amplitude=False)
|
||||
self.assertGreater(np.abs(waveform.amp), 1.0)
|
||||
|
||||
def test_sech_deriv_limit_amplitude(self):
|
||||
"""Test that the check for amplitude less than or equal to 1 can be disabled."""
|
||||
with self.assertRaises(PulseError):
|
||||
SechDeriv(duration=100, amp=5, sigma=1)
|
||||
|
||||
with patch("qiskit.pulse.library.pulse.Pulse.limit_amplitude", new=False):
|
||||
waveform = SechDeriv(duration=100, amp=5, sigma=1)
|
||||
self.assertGreater(np.abs(waveform.amp) / waveform.sigma, 2.0)
|
||||
|
||||
def test_sech_deriv_limit_amplitude_per_instance(self):
|
||||
"""Test that the check for amplitude per instance."""
|
||||
with self.assertRaises(PulseError):
|
||||
SechDeriv(duration=100, amp=5, sigma=1)
|
||||
|
||||
waveform = SechDeriv(duration=100, amp=5, sigma=1, limit_amplitude=False)
|
||||
self.assertGreater(np.abs(waveform.amp) / waveform.sigma, 2.0)
|
||||
|
||||
def test_get_parameters(self):
|
||||
"""Test getting pulse parameters as attribute."""
|
||||
drag_pulse = Drag(duration=100, amp=0.1, sigma=40, beta=3)
|
||||
|
|
Loading…
Reference in New Issue