From a09449f7f380789975de4fff410580d6d10eaf88 Mon Sep 17 00:00:00 2001 From: dhruvbhq Date: Mon, 21 Jun 2021 23:42:06 +0530 Subject: [PATCH 1/3] fixed issue 6544 by propagating limit_amplitude keyword from constructor of Pulse base class to ParametricPulse classes --- qiskit/pulse/library/parametric_pulses.py | 29 ++++++++++++---- ...in-parametric-pulses-ef88b77db8c1b06c.yaml | 10 ++++++ test/python/pulse/test_parameters.py | 34 +++++++++++++++++++ 3 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml diff --git a/qiskit/pulse/library/parametric_pulses.py b/qiskit/pulse/library/parametric_pulses.py index 2a04ed245cdf..ff05985f4b78 100644 --- a/qiskit/pulse/library/parametric_pulses.py +++ b/qiskit/pulse/library/parametric_pulses.py @@ -55,14 +55,20 @@ class ParametricPulse(Pulse): """The abstract superclass for parametric pulses.""" @abstractmethod - def __init__(self, duration: Union[int, ParameterExpression], name: Optional[str] = None): + def __init__( + self, + duration: Union[int, ParameterExpression], + name: Optional[str] = None, + limit_amplitude: Optional[bool] = None, + ): """Create a parametric pulse and validate the input parameters. Args: duration: Pulse length in terms of the the sampling period `dt`. name: Display name for this pulse envelope. + limit_amplitude: Passed to parent Pulse """ - super().__init__(duration=duration, name=name) + super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) self.validate_parameters() @abstractmethod @@ -141,6 +147,7 @@ def __init__( amp: Union[complex, ParameterExpression], sigma: Union[float, ParameterExpression], name: Optional[str] = None, + limit_amplitude: Optional[bool] = None, ): """Initialize the gaussian pulse. @@ -150,12 +157,13 @@ def __init__( sigma: A measure of how wide or narrow the Gaussian peak is; described mathematically in the class docstring. name: Display name for this pulse envelope. + limit_amplitude: Passed to parent ParametricPulse """ if not _is_parameterized(amp): amp = complex(amp) self._amp = amp self._sigma = sigma - super().__init__(duration=duration, name=name) + super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) @property def amp(self) -> Union[complex, ParameterExpression]: @@ -235,6 +243,7 @@ def __init__( width: Union[float, ParameterExpression] = None, risefall_sigma_ratio: Union[float, ParameterExpression] = None, name: Optional[str] = None, + limit_amplitude: Optional[bool] = None, ): """Initialize the gaussian square pulse. @@ -246,6 +255,7 @@ def __init__( width: The duration of the embedded square pulse. risefall_sigma_ratio: The ratio of each risefall duration to sigma. name: Display name for this pulse envelope. + limit_amplitude: Passed to parent ParametricPulse """ if not _is_parameterized(amp): amp = complex(amp) @@ -253,7 +263,7 @@ def __init__( self._sigma = sigma self._risefall_sigma_ratio = risefall_sigma_ratio self._width = width - super().__init__(duration=duration, name=name) + super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) @property def amp(self) -> Union[complex, ParameterExpression]: @@ -382,6 +392,7 @@ def __init__( sigma: Union[float, ParameterExpression], beta: Union[float, ParameterExpression], name: Optional[str] = None, + limit_amplitude: Optional[bool] = None, ): """Initialize the drag pulse. @@ -392,13 +403,14 @@ def __init__( in the class docstring. beta: The correction amplitude. name: Display name for this pulse envelope. + limit_amplitude: Passed to parent ParametricPulse """ if not _is_parameterized(amp): amp = complex(amp) self._amp = amp self._sigma = sigma self._beta = beta - super().__init__(duration=duration, name=name) + super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) @property def amp(self) -> Union[complex, ParameterExpression]: @@ -435,9 +447,10 @@ def validate_parameters(self) -> None: not _is_parameterized(self.beta) and not _is_parameterized(self.sigma) and self.beta > self.sigma + and self.limit_amplitude ): # If beta <= sigma, then the maximum amplitude is at duration / 2, which is - # already constrainted by self.amp <= 1 + # already constrained by self.amp <= 1 # 1. Find the first maxima associated with the beta * d/dx gaussian term # This eq is derived from solving for the roots of the norm of the drag function. @@ -491,6 +504,7 @@ def __init__( duration: Union[int, ParameterExpression], amp: Union[complex, ParameterExpression], name: Optional[str] = None, + limit_amplitude: Optional[bool] = None, ): """ Initialize the constant-valued pulse. @@ -499,11 +513,12 @@ def __init__( duration: Pulse length in terms of the the sampling period `dt`. amp: The amplitude of the constant square pulse. name: Display name for this pulse envelope. + limit_amplitude: Passed to parent ParametricPulse """ if not _is_parameterized(amp): amp = complex(amp) self._amp = amp - super().__init__(duration=duration, name=name) + super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) @property def amp(self) -> Union[complex, ParameterExpression]: diff --git a/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml b/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml new file mode 100644 index 000000000000..1c3c62394466 --- /dev/null +++ b/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml @@ -0,0 +1,10 @@ +--- +features: + - | + Adds an argument 'limit_amplitude' to the constructor of ParametricPulse + class, and derived classes Gaussian, GaussianSquare, Drag and Constant, to + enable or disable the amplitude limit of 1 on the pulse. Fixes #6544. + This option gets propagated to the parent class Pulse. With this option + enabled, ParametricPulse class and its subclasses do not allow amplitudes + larger than 1. By default, the value of 'limit_amplitude' is true, so that + the amplitude is constrained to be less than 1. diff --git a/test/python/pulse/test_parameters.py b/test/python/pulse/test_parameters.py index 34201373bf23..894e0c17503b 100644 --- a/test/python/pulse/test_parameters.py +++ b/test/python/pulse/test_parameters.py @@ -274,6 +274,40 @@ def test_parametric_pulses_parameter_assignment(self): self.assertEqual(waveform.amp, self.amp) self.assertEqual(waveform.sigma, 12.7) + def test_parametric_pulses_limit_amplitude(self): + """Test that the check for amplitude less than or equal to 1 can be disabled.""" + waveform = pulse.library.Gaussian( + duration=100, sigma=1.0, amp=1.1 + 0.8j, limit_amplitude=False + ) + self.assertGreater(np.abs(waveform.amp), 1.0) + with self.assertRaises(PulseError): + waveform = pulse.library.Gaussian( + duration=100, sigma=1.0, amp=1.1 + 0.8j, limit_amplitude=True + ) + + waveform = pulse.library.GaussianSquare( + duration=100, sigma=1.0, amp=1.1 + 0.8j, width=10, limit_amplitude=False + ) + self.assertGreater(np.abs(waveform.amp), 1.0) + with self.assertRaises(PulseError): + waveform = pulse.library.GaussianSquare( + duration=100, sigma=1.0, amp=1.1 + 0.8j, width=10, limit_amplitude=True + ) + + waveform = pulse.library.Drag( + duration=100, sigma=1.0, beta=1.0, amp=1.1 + 0.8j, limit_amplitude=False + ) + self.assertGreater(np.abs(waveform.amp), 1.0) + with self.assertRaises(PulseError): + waveform = pulse.library.Drag( + duration=100, sigma=1.0, beta=1.0, amp=1.1 + 0.8j, limit_amplitude=True + ) + + waveform = pulse.library.Constant(duration=100, amp=1.1 + 0.8j, limit_amplitude=False) + self.assertGreater(np.abs(waveform.amp), 1.0) + with self.assertRaises(PulseError): + waveform = pulse.library.Constant(duration=100, amp=1.1 + 0.8j, limit_amplitude=True) + @unittest.skip("Not yet supported by ParameterExpression") def test_complex_value_assignment(self): """Test that complex values can be assigned to Parameters.""" From 9b816b95c32363071825a801c4b6d9a2b45aa70d Mon Sep 17 00:00:00 2001 From: dhruvbhq Date: Mon, 26 Jul 2021 22:26:04 +0530 Subject: [PATCH 2/3] Added more explanation in doc of limit_ampltude --- qiskit/pulse/library/parametric_pulses.py | 30 +++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/qiskit/pulse/library/parametric_pulses.py b/qiskit/pulse/library/parametric_pulses.py index ff05985f4b78..26a8c7a3f1e2 100644 --- a/qiskit/pulse/library/parametric_pulses.py +++ b/qiskit/pulse/library/parametric_pulses.py @@ -66,7 +66,11 @@ def __init__( Args: duration: Pulse length in terms of the the sampling period `dt`. name: Display name for this pulse envelope. - limit_amplitude: Passed to parent Pulse + limit_amplitude: If ``True``, then limit the amplitude of the + waveform to 1. By default it is ``True`` and the + amplitude is constrained to 1. This restriction + can be overruled via this argument. Passed to + parent Pulse. """ super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) self.validate_parameters() @@ -157,7 +161,11 @@ def __init__( sigma: A measure of how wide or narrow the Gaussian peak is; described mathematically in the class docstring. name: Display name for this pulse envelope. - limit_amplitude: Passed to parent ParametricPulse + limit_amplitude: If ``True``, then limit the amplitude of the + waveform to 1. By default it is ``True`` and the + amplitude is constrained to 1. This restriction + can be overruled via this argument. Passed to + parent ParametricPulse. """ if not _is_parameterized(amp): amp = complex(amp) @@ -255,7 +263,11 @@ def __init__( width: The duration of the embedded square pulse. risefall_sigma_ratio: The ratio of each risefall duration to sigma. name: Display name for this pulse envelope. - limit_amplitude: Passed to parent ParametricPulse + limit_amplitude: If ``True``, then limit the amplitude of the + waveform to 1. By default it is ``True`` and the + amplitude is constrained to 1. This restriction + can be overruled via this argument. Passed to + parent ParametricPulse. """ if not _is_parameterized(amp): amp = complex(amp) @@ -403,7 +415,11 @@ def __init__( in the class docstring. beta: The correction amplitude. name: Display name for this pulse envelope. - limit_amplitude: Passed to parent ParametricPulse + limit_amplitude: If ``True``, then limit the amplitude of the + waveform to 1. By default it is ``True`` and the + amplitude is constrained to 1. This restriction + can be overruled via this argument. Passed to + parent ParametricPulse. """ if not _is_parameterized(amp): amp = complex(amp) @@ -513,7 +529,11 @@ def __init__( duration: Pulse length in terms of the the sampling period `dt`. amp: The amplitude of the constant square pulse. name: Display name for this pulse envelope. - limit_amplitude: Passed to parent ParametricPulse + limit_amplitude: If ``True``, then limit the amplitude of the + waveform to 1. By default it is ``True`` and the + amplitude is constrained to 1. This restriction + can be overruled via this argument. Passed to + parent ParametricPulse. """ if not _is_parameterized(amp): amp = complex(amp) From 87c3f7fb1e22933700d9eb5d6fcf19a74900ffe2 Mon Sep 17 00:00:00 2001 From: dhruvbhq Date: Tue, 27 Jul 2021 21:49:53 +0530 Subject: [PATCH 3/3] Implemented documentation related suggestions --- qiskit/pulse/library/parametric_pulses.py | 30 +++++++------------ ...in-parametric-pulses-ef88b77db8c1b06c.yaml | 12 ++++---- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/qiskit/pulse/library/parametric_pulses.py b/qiskit/pulse/library/parametric_pulses.py index 26a8c7a3f1e2..17e6bc2f902a 100644 --- a/qiskit/pulse/library/parametric_pulses.py +++ b/qiskit/pulse/library/parametric_pulses.py @@ -67,10 +67,8 @@ def __init__( duration: Pulse length in terms of the the sampling period `dt`. name: Display name for this pulse envelope. limit_amplitude: If ``True``, then limit the amplitude of the - waveform to 1. By default it is ``True`` and the - amplitude is constrained to 1. This restriction - can be overruled via this argument. Passed to - parent Pulse. + waveform to 1. The default is ``True`` and the + amplitude is constrained to 1. """ super().__init__(duration=duration, name=name, limit_amplitude=limit_amplitude) self.validate_parameters() @@ -162,10 +160,8 @@ def __init__( in the class docstring. name: Display name for this pulse envelope. limit_amplitude: If ``True``, then limit the amplitude of the - waveform to 1. By default it is ``True`` and the - amplitude is constrained to 1. This restriction - can be overruled via this argument. Passed to - parent ParametricPulse. + waveform to 1. The default is ``True`` and the + amplitude is constrained to 1. """ if not _is_parameterized(amp): amp = complex(amp) @@ -264,10 +260,8 @@ def __init__( risefall_sigma_ratio: The ratio of each risefall duration to sigma. name: Display name for this pulse envelope. limit_amplitude: If ``True``, then limit the amplitude of the - waveform to 1. By default it is ``True`` and the - amplitude is constrained to 1. This restriction - can be overruled via this argument. Passed to - parent ParametricPulse. + waveform to 1. The default is ``True`` and the + amplitude is constrained to 1. """ if not _is_parameterized(amp): amp = complex(amp) @@ -416,10 +410,8 @@ def __init__( beta: The correction amplitude. name: Display name for this pulse envelope. limit_amplitude: If ``True``, then limit the amplitude of the - waveform to 1. By default it is ``True`` and the - amplitude is constrained to 1. This restriction - can be overruled via this argument. Passed to - parent ParametricPulse. + waveform to 1. The default is ``True`` and the + amplitude is constrained to 1. """ if not _is_parameterized(amp): amp = complex(amp) @@ -530,10 +522,8 @@ def __init__( amp: The amplitude of the constant square pulse. name: Display name for this pulse envelope. limit_amplitude: If ``True``, then limit the amplitude of the - waveform to 1. By default it is ``True`` and the - amplitude is constrained to 1. This restriction - can be overruled via this argument. Passed to - parent ParametricPulse. + waveform to 1. The default is ``True`` and the + amplitude is constrained to 1. """ if not _is_parameterized(amp): amp = complex(amp) diff --git a/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml b/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml index 1c3c62394466..106aeedf5317 100644 --- a/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml +++ b/releasenotes/notes/add-support-to-disable-amplitude-limit-in-parametric-pulses-ef88b77db8c1b06c.yaml @@ -1,10 +1,10 @@ --- features: - | - Adds an argument 'limit_amplitude' to the constructor of ParametricPulse + Adds an argument ``limit_amplitude`` to the constructor of ParametricPulse class, and derived classes Gaussian, GaussianSquare, Drag and Constant, to - enable or disable the amplitude limit of 1 on the pulse. Fixes #6544. - This option gets propagated to the parent class Pulse. With this option - enabled, ParametricPulse class and its subclasses do not allow amplitudes - larger than 1. By default, the value of 'limit_amplitude' is true, so that - the amplitude is constrained to be less than 1. + enable or disable the amplitude limit of 1 on the pulse. Fixes #6544. This + option gets propagated to the parent class Pulse. With this option enabled, + ParametricPulse class and its subclasses do not allow amplitudes larger + than 1. By default, the value of ``limit_amplitude`` is true, so that the + amplitude is constrained to be less than 1.