Skip to content

Commit

Permalink
Use round instead of ceil for GaussianSquare pulse duration in RZXCal…
Browse files Browse the repository at this point in the history
…ibrationBuilder (#7995)

* round duration instead of ceil

* update test

* add test

* add release note

* Update releasenotes/notes/pulse-round-a014390e414c79c8.yaml

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
  • Loading branch information
4 people authored May 10, 2022
1 parent ec9d693 commit 7726d47
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 14 deletions.
4 changes: 2 additions & 2 deletions qiskit/transpiler/passes/calibration/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,14 @@ def rescale_cr_inst(instruction: Play, theta: float, sample_mult: int = 16) -> P

if target_area > gaussian_area:
width = (target_area - gaussian_area) / abs(amp)
duration = math.ceil((width + n_sigmas * sigma) / sample_mult) * sample_mult
duration = round((width + n_sigmas * sigma) / sample_mult) * sample_mult
return Play(
GaussianSquare(amp=sign * amp, width=width, sigma=sigma, duration=duration),
channel=instruction.channel,
)
else:
amp_scale = sign * target_area / gaussian_area
duration = math.ceil(n_sigmas * sigma / sample_mult) * sample_mult
duration = round(n_sigmas * sigma / sample_mult) * sample_mult
return Play(
GaussianSquare(amp=amp * amp_scale, width=0, sigma=sigma, duration=duration),
channel=instruction.channel,
Expand Down
5 changes: 5 additions & 0 deletions releasenotes/notes/pulse-round-a014390e414c79c8.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Fixes a bug in the :class:`~.RZXCalibrationBuilder` transpiler pass that was causing pulses to sometimes be
constructed with incorrect durations.
43 changes: 31 additions & 12 deletions test/python/pulse/test_calibrationbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,20 @@

"""Test the RZXCalibrationBuilderNoEcho."""

from math import pi, erf, ceil
from math import erf, pi

import numpy as np
from ddt import data, ddt

from qiskit import circuit, schedule
from qiskit.transpiler import PassManager
from qiskit.pulse import ControlChannel, Delay, DriveChannel, GaussianSquare, Play, ShiftPhase
from qiskit.test import QiskitTestCase
from qiskit.pulse import (
Play,
Delay,
ShiftPhase,
ControlChannel,
DriveChannel,
GaussianSquare,
)
from qiskit.test.mock import FakeAthens
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes.calibration.builders import (
RZXCalibrationBuilder,
RZXCalibrationBuilderNoEcho,
)
from qiskit.test.mock import FakeAthens


class TestCalibrationBuilder(QiskitTestCase):
Expand All @@ -42,6 +37,30 @@ def setUp(self):
self.inst_map = self.backend.defaults().instruction_schedule_map


@ddt
class TestRZXCalibrationBuilder(TestCalibrationBuilder):
"""Test RZXCalibrationBuilder."""

@data(np.pi / 4, np.pi / 2, np.pi)
def test_rzx_calibration_builder_duration(self, theta: float):
"""Test that pulse durations are computed correctly."""
width = 512.00000001
sigma = 64
n_sigmas = 4
duration = width + n_sigmas * sigma
sample_mult = 16
amp = 1.0
pulse = GaussianSquare(duration=duration, amp=amp, sigma=sigma, width=width)
instruction = Play(pulse, ControlChannel(1))
scaled = RZXCalibrationBuilder.rescale_cr_inst(instruction, theta, sample_mult=sample_mult)
gaussian_area = abs(amp) * sigma * np.sqrt(2 * np.pi) * erf(n_sigmas)
area = gaussian_area + abs(amp) * width
target_area = abs(theta) / (np.pi / 2.0) * area
width = (target_area - gaussian_area) / abs(amp)
expected_duration = round((width + n_sigmas * sigma) / sample_mult) * sample_mult
self.assertEqual(scaled.duration, expected_duration)


class TestRZXCalibrationBuilderNoEcho(TestCalibrationBuilder):
"""Test RZXCalibrationBuilderNoEcho."""

Expand Down Expand Up @@ -98,7 +117,7 @@ def test_rzx_calibration_builder(self):
area = gaussian_area + abs(amp) * width
target_area = abs(theta) / (np.pi / 2.0) * area
width = (target_area - gaussian_area) / abs(amp)
duration = ceil((width + n_sigmas * sigma) / sample_mult) * sample_mult
duration = round((width + n_sigmas * sigma) / sample_mult) * sample_mult

# Check whether the durations of the RZX pulse and
# the scaled CR pulse from the CX gate match.
Expand Down

0 comments on commit 7726d47

Please sign in to comment.