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

Converting the pulse library from complex amp to amp+angle #9002

Merged
merged 27 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
03129e2
Converting Gaussian SymbolicPulse from complex amp to amp,angle.
TsafrirA Oct 26, 2022
e7a0bf7
removed unnecessary import.
TsafrirA Oct 26, 2022
0310fbd
Completed the changes.
TsafrirA Nov 10, 2022
786c000
Bug fix and test updates.
TsafrirA Nov 13, 2022
a591f66
removed commented line.
TsafrirA Nov 13, 2022
dbe43fb
black correction.
TsafrirA Nov 14, 2022
8a74b70
Tests correction.
TsafrirA Nov 14, 2022
22c61b9
Bump QPY version, and adjust QPY loader.
TsafrirA Nov 20, 2022
04dcd0e
Release Notes.
TsafrirA Nov 21, 2022
4d1ea59
Update qiskit/qobj/converters/pulse_instruction.py
TsafrirA Nov 21, 2022
4412df6
Update releasenotes/notes/Symbolic-Pulses-conversion-to-amp-angle-0c6…
TsafrirA Nov 21, 2022
54bcdf2
Some more corrections.
TsafrirA Nov 21, 2022
fbe5ead
QPY load adjustment.
TsafrirA Nov 23, 2022
1a6db4a
Removed debug print
TsafrirA Nov 24, 2022
d7d4927
Always add "angle" to envelope
TsafrirA Nov 26, 2022
211838a
black
TsafrirA Nov 26, 2022
e07a2c5
Update qiskit/qpy/__init__.py
TsafrirA Nov 28, 2022
8e1db4f
resolve conflict
TsafrirA Nov 28, 2022
c9d128f
Merge branch 'main' into AmpAngle
TsafrirA Nov 28, 2022
ee394ef
Remove outdated test.
TsafrirA Nov 28, 2022
0cc531b
Lint
TsafrirA Nov 28, 2022
048a53b
Release notes style
TsafrirA Nov 28, 2022
b69940b
Removed QPY version bump in favor of using qiskit terra version as an…
TsafrirA Nov 29, 2022
55262a2
bug fix
TsafrirA Nov 30, 2022
fb07443
bug fix
TsafrirA Nov 30, 2022
8c7281c
Merge branch 'main' into AmpAngle
TsafrirA Nov 30, 2022
97f6786
Merge branch 'main' into AmpAngle
mergify[bot] Nov 30, 2022
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
49 changes: 45 additions & 4 deletions qiskit/pulse/library/symbolic_pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,28 @@ def valid_amp_conditions(self) -> sym.Expr:
"""Return symbolic expression for the pulse amplitude constraints."""
return self._valid_amp_conditions

# This should be removed once the complex amp deprecation is completed.
@property
def amp(self) -> Union[ParameterExpression, complex]:
if "amp" in self._params:
if isinstance(self._params["amp"], complex):
warnings.warn(
f"{self.__class__.__name__}.amp returns the complex amplitude which will be deprecated. "
f"Use {self.__class__.__name__}.amp_angle to get the magnitude of the amplitude and the complex angle "
"as a tuple",
PendingDeprecationWarning
)
return self._params["amp"]
else:
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute 'amp'")

@property
def amp_angle(self) -> tuple:
TsafrirA marked this conversation as resolved.
Show resolved Hide resolved
if "amp" in self._params:
return np.abs(self._params["amp"]), np.angle(self._params["amp"])
else:
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute 'amp_angle'")

def get_waveform(self) -> Waveform:
r"""Return a Waveform with samples filled according to the formula that the pulse
represents and the parameter values it contains.
Expand Down Expand Up @@ -614,7 +636,7 @@ class Gaussian(metaclass=_PulseType):
.. math::

f'(x) &= \exp\Bigl( -\frac12 \frac{{(x - \text{duration}/2)}^2}{\text{sigma}^2} \Bigr)\\
f(x) &= \text{amp} \times \frac{f'(x) - f'(-1)}{1-f'(-1)}, \quad 0 \le x < \text{duration}
f(x) &= \text{amp} \times \exp\left(i\text{angle}\right) \times \frac{f'(x) - f'(-1)}{1-f'(-1)}, \quad 0 \le x < \text{duration}

where :math:`f'(x)` is the gaussian waveform without lifting or amplitude scaling.
"""
Expand All @@ -624,26 +646,45 @@ class Gaussian(metaclass=_PulseType):
def __new__(
cls,
duration: Union[int, ParameterExpression],
amp: Union[complex, ParameterExpression],
amp: Union[complex, float, ParameterExpression],
sigma: Union[float, ParameterExpression],
angle: Optional[Union[float, ParameterExpression]] = None,
name: Optional[str] = None,
limit_amplitude: Optional[bool] = None,
) -> SymbolicPulse:
"""Create new pulse instance.

Args:
duration: Pulse length in terms of the sampling period `dt`.
amp: The amplitude of the Gaussian envelope.
amp: The magnitude of the amplitude of the Gaussian envelope. Complex amp support will be deprecated.
sigma: A measure of how wide or narrow the Gaussian peak is; described mathematically
in the class docstring.
angle: The angle of the complex amplitude of the Gaussian envelope. 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:
SymbolicPulse instance.
"""
parameters = {"amp": amp, "sigma": sigma}
# This should be removed once complex amp support is deprecated.
if isinstance(amp, complex):
if angle is None:
warnings.warn(
"Complex amp will be deprecated. Use float amp (for the magnitude) and float angle instead.",
PendingDeprecationWarning
)
else:
raise PulseError("amp can't be complex when providing angle")

if isinstance(amp, float):
if amp < 0:
raise PulseError("'amp' has to be positive (use 'angle' to set sign)")
TsafrirA marked this conversation as resolved.
Show resolved Hide resolved

if angle is None:
angle = 0

parameters = {"amp": amp*np.exp(1j*angle), "sigma": sigma}

# Prepare symbolic expressions
_t, _duration, _amp, _sigma = sym.symbols("t, duration, amp, sigma")
Expand Down
18 changes: 18 additions & 0 deletions test/python/pulse/test_pulse_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ def test_construction(self):
Constant(duration=150, amp=0.1 + 0.4j)
Drag(duration=25, amp=0.2 + 0.3j, sigma=7.8, beta=4)

# This test should be removed once deprecation of complex amp is completed.
def test_complex_amp_deprecation(self):
"""Test that deprecation warnings and errors are raised for complex amp"""
with self.assertWarns(PendingDeprecationWarning):
TsafrirA marked this conversation as resolved.
Show resolved Hide resolved
Gaussian(duration=25, sigma=4, amp=0.5j)
with self.assertRaises(PulseError):
Gaussian(duration=25, sigma=4, amp=0.5j, angle=1)

gauss_pulse_complex_amp = Gaussian(duration=25, sigma=4, amp=0.5j)
TsafrirA marked this conversation as resolved.
Show resolved Hide resolved
with self.assertWarns(PendingDeprecationWarning):
complex_amp = gauss_pulse_complex_amp.amp
amp_magnitude , angle = gauss_pulse_complex_amp.amp_angle
np.testing.assert_almost_equal(complex_amp, amp_magnitude*np.exp(1j*angle))

gauss_pulse_amp_angle = Gaussian(duration=25, sigma=4, amp=0.5, angle=np.pi/2)
np.testing.assert_almost_equal(gauss_pulse_amp_angle.get_waveform().samples,
gauss_pulse_complex_amp.get_waveform().samples)

def test_gaussian_pulse(self):
"""Test that Gaussian sample pulse matches the pulse library."""
gauss = Gaussian(duration=25, sigma=4, amp=0.5j)
Expand Down