Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Begin deprecation cycle of the discrete pulse library #10222

Merged
merged 10 commits into from
Jul 4, 2023
13 changes: 10 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"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 -------------------------------------------------
Expand Down Expand Up @@ -112,17 +112,24 @@
"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"


# -- 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 = ""
4 changes: 4 additions & 0 deletions qiskit/pulse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@
Cos,
Sawtooth,
Triangle,
Square,
GaussianDeriv,
Sech,
SechDeriv,
ParametricPulse,
SymbolicPulse,
ScalableSymbolicPulse,
Expand Down
8 changes: 8 additions & 0 deletions qiskit/pulse/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,14 @@
GaussianSquare
GaussianSquareDrag
gaussian_square_echo
GaussianDeriv
Sin
Cos
Sawtooth
Triangle
Square
Sech
SechDeriv
"""

Expand All @@ -119,12 +123,16 @@
GaussianSquare,
GaussianSquareDrag,
gaussian_square_echo,
GaussianDeriv,
Drag,
Constant,
Sin,
Cos,
Sawtooth,
Triangle,
Square,
Sech,
SechDeriv,
)
from .pulse import Pulse
from .waveform import Waveform
2 changes: 1 addition & 1 deletion qiskit/pulse/library/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
125 changes: 124 additions & 1 deletion qiskit/pulse/library/discrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"""
from typing import Optional

from qiskit.utils.deprecation import deprecate_func
from ..exceptions import PulseError
from .waveform import Waveform
from . import continuous
Expand All @@ -26,6 +27,16 @@
_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"
nkanazawa1989 marked this conversation as resolved.
Show resolved Hide resolved
" 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`.
Expand All @@ -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().",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also define Zero function in the symbolic pulse module that wraps Constant with amp=0.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here. I don't know how much people actually use zero amplitude constants as spacers (@wshanks correctly pointed out elsewhere that there are use cases where you would want something like this) but I suspect it doesn't warrant the extra clutter in the code base.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a problem of backward compatibility of import. Once we remove this module, people cannot find zero in the pulse namespace and there is no alternative approach in terms of import. Likely this pulse is not significantly important and can go in this way.

pending=True,
)
def zero(duration: int, name: Optional[str] = None) -> Waveform:
"""Generates zero-sampled :class:`~qiskit.pulse.library.Waveform`.
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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``.
Expand All @@ -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:
Expand Down Expand Up @@ -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`.
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Loading