Skip to content

Commit 9cf239c

Browse files
committed
Fix scheduling tests, lints and docs issue.
1 parent 25d0858 commit 9cf239c

2 files changed

Lines changed: 228 additions & 30 deletions

File tree

qiskit/pulse/builder.py

Lines changed: 211 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,20 @@ def append_instruction(instruction: instructions.Instruction):
736736
def num_qubits() -> int:
737737
"""Return number of qubits in the currently active backend.
738738
739+
Examples:
740+
741+
.. code-block:: python
742+
743+
from qiskit import pulse
744+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
745+
backend = FakeOpenPulse2Q()
746+
with pulse.build(backend):
747+
print(pulse.num_qubits())
748+
749+
.. code-block:: text
750+
751+
2
752+
739753
.. note:: Requires the active builder context to have a backend set.
740754
"""
741755
if isinstance(active_backend(), BackendV2):
@@ -780,6 +794,20 @@ def samples_to_seconds(samples: int | np.ndarray) -> float | np.ndarray:
780794
def qubit_channels(qubit: int) -> set[chans.Channel]:
781795
"""Returns the set of channels associated with a qubit.
782796
797+
Examples:
798+
799+
.. code-block:: python
800+
801+
from qiskit import pulse
802+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
803+
backend = FakeOpenPulse2Q()
804+
with pulse.build(backend):
805+
print(pulse.qubit_channels(0))
806+
807+
.. code-block:: text
808+
809+
{MeasureChannel(0), ControlChannel(0), DriveChannel(0), AcquireChannel(0), ControlChannel(1)}
810+
783811
.. note:: Requires the active builder context to have a backend set.
784812
785813
.. note:: A channel may still be associated with another qubit in this list
@@ -1145,6 +1173,33 @@ def frequency_offset(
11451173
) -> Generator[None, None, None]:
11461174
"""Shift the frequency of inputs channels on entry into context and undo on exit.
11471175
1176+
Examples:
1177+
1178+
.. code-block:: python
1179+
1180+
from qiskit import pulse
1181+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1182+
1183+
backend = FakeOpenPulse2Q()
1184+
d0 = pulse.DriveChannel(0)
1185+
1186+
with pulse.build(backend) as pulse_prog:
1187+
# shift frequency by 1GHz
1188+
with pulse.frequency_offset(1e9, d0):
1189+
pulse.play(pulse.Constant(10, 1.0), d0)
1190+
1191+
assert len(pulse_prog.instructions) == 3
1192+
1193+
with pulse.build(backend) as pulse_prog:
1194+
# Shift frequency by 1GHz.
1195+
# Undo accumulated phase in the shifted frequency frame
1196+
# when exiting the context.
1197+
with pulse.frequency_offset(1e9, d0, compensate_phase=True):
1198+
pulse.play(pulse.Constant(10, 1.0), d0)
1199+
1200+
assert len(pulse_prog.instructions) == 4
1201+
1202+
11481203
Args:
11491204
frequency: Amount of frequency offset in Hz.
11501205
channels: Channels to offset frequency of.
@@ -1182,6 +1237,18 @@ def frequency_offset(
11821237
def drive_channel(qubit: int) -> chans.DriveChannel:
11831238
"""Return ``DriveChannel`` for ``qubit`` on the active builder backend.
11841239
1240+
Examples:
1241+
1242+
.. code-block:: python
1243+
1244+
from qiskit import pulse
1245+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1246+
1247+
backend = FakeOpenPulse2Q()
1248+
1249+
with pulse.build(backend):
1250+
assert pulse.drive_channel(0) == pulse.DriveChannel(0)
1251+
11851252
.. note:: Requires the active builder context to have a backend set.
11861253
"""
11871254
# backendV2
@@ -1194,6 +1261,18 @@ def drive_channel(qubit: int) -> chans.DriveChannel:
11941261
def measure_channel(qubit: int) -> chans.MeasureChannel:
11951262
"""Return ``MeasureChannel`` for ``qubit`` on the active builder backend.
11961263
1264+
Examples:
1265+
1266+
.. code-block:: python
1267+
1268+
from qiskit import pulse
1269+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1270+
1271+
backend = FakeOpenPulse2Q()
1272+
1273+
with pulse.build(backend):
1274+
assert pulse.measure_channel(0) == pulse.MeasureChannel(0)
1275+
11971276
.. note:: Requires the active builder context to have a backend set.
11981277
"""
11991278
# backendV2
@@ -1206,6 +1285,18 @@ def measure_channel(qubit: int) -> chans.MeasureChannel:
12061285
def acquire_channel(qubit: int) -> chans.AcquireChannel:
12071286
"""Return ``AcquireChannel`` for ``qubit`` on the active builder backend.
12081287
1288+
Examples:
1289+
1290+
.. code-block:: python
1291+
1292+
from qiskit import pulse
1293+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1294+
1295+
backend = FakeOpenPulse2Q()
1296+
1297+
with pulse.build(backend):
1298+
assert pulse.acquire_channel(0) == pulse.AcquireChannel(0)
1299+
12091300
.. note:: Requires the active builder context to have a backend set.
12101301
"""
12111302
# backendV2
@@ -1221,6 +1312,18 @@ def control_channels(*qubits: Iterable[int]) -> list[chans.ControlChannel]:
12211312
Return the secondary drive channel for the given qubit -- typically
12221313
utilized for controlling multi-qubit interactions.
12231314
1315+
Examples:
1316+
1317+
.. code-block:: python
1318+
1319+
from qiskit import pulse
1320+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1321+
1322+
backend = FakeOpenPulse2Q()
1323+
1324+
with pulse.build(backend):
1325+
assert pulse.control_channels(0, 1) == [pulse.ControlChannel(0)]
1326+
12241327
.. note:: Requires the active builder context to have a backend set.
12251328
12261329
Args:
@@ -1710,8 +1813,65 @@ def barrier(*channels_or_qubits: chans.Channel | int, name: str | None = None):
17101813
"""Barrier directive for a set of channels and qubits.
17111814
17121815
This directive prevents the compiler from moving instructions across
1713-
the barrier. The barrier allows the pulse compiler to take care of more advanced
1714-
scheduling alignment operations across channels.
1816+
the barrier. Consider the case where we want to enforce that one pulse
1817+
happens after another on separate channels, this can be done with:
1818+
1819+
.. code-block:: python
1820+
1821+
from qiskit import pulse
1822+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1823+
1824+
backend = FakeOpenPulse2Q()
1825+
1826+
d0 = pulse.DriveChannel(0)
1827+
d1 = pulse.DriveChannel(1)
1828+
1829+
with pulse.build(backend) as barrier_pulse_prog:
1830+
pulse.play(pulse.Constant(10, 1.0), d0)
1831+
pulse.barrier(d0, d1)
1832+
pulse.play(pulse.Constant(10, 1.0), d1)
1833+
1834+
Of course this could have been accomplished with:
1835+
1836+
.. code-block:: python
1837+
1838+
from qiskit.pulse import transforms
1839+
1840+
with pulse.build(backend) as aligned_pulse_prog:
1841+
with pulse.align_sequential():
1842+
pulse.play(pulse.Constant(10, 1.0), d0)
1843+
pulse.play(pulse.Constant(10, 1.0), d1)
1844+
1845+
barrier_pulse_prog = transforms.target_qobj_transform(barrier_pulse_prog)
1846+
aligned_pulse_prog = transforms.target_qobj_transform(aligned_pulse_prog)
1847+
1848+
assert barrier_pulse_prog == aligned_pulse_prog
1849+
1850+
The barrier allows the pulse compiler to take care of more advanced
1851+
scheduling alignment operations across channels. For example
1852+
in the case where we are calling an outside circuit or schedule and
1853+
want to align a pulse at the end of one call:
1854+
1855+
.. code-block:: python
1856+
1857+
import math
1858+
from qiskit import pulse
1859+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1860+
1861+
backend = FakeOpenPulse2Q()
1862+
1863+
d0 = pulse.DriveChannel(0)
1864+
1865+
with pulse.build(backend) as pulse_prog:
1866+
with pulse.align_right():
1867+
pulse.call(backend.defaults().instruction_schedule_map.get('u1', (1,)))
1868+
# Barrier qubit 1 and d0.
1869+
pulse.barrier(1, d0)
1870+
# Due to barrier this will play before the gate on qubit 1.
1871+
pulse.play(pulse.Constant(10, 1.0), d0)
1872+
# This will end at the same time as the pulse above due to
1873+
# the barrier.
1874+
pulse.call(backend.defaults().instruction_schedule_map.get('u1', (1,)))
17151875
17161876
.. note:: Requires the active builder context to have a backend set if
17171877
qubits are barriered on.
@@ -1735,6 +1895,29 @@ def macro(func: Callable):
17351895
behave as if the function code was embedded inline in the parent builder context
17361896
after parameter substitution.
17371897
1898+
Examples:
1899+
1900+
.. code-block:: python
1901+
1902+
from qiskit import pulse
1903+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
1904+
1905+
@pulse.macro
1906+
def measure(qubit: int):
1907+
pulse.play(pulse.GaussianSquare(16384, 256, 15872), pulse.measure_channel(qubit))
1908+
mem_slot = pulse.MemorySlot(qubit)
1909+
pulse.acquire(16384, pulse.acquire_channel(qubit), mem_slot)
1910+
1911+
return mem_slot
1912+
1913+
backend = FakeOpenPulse2Q()
1914+
1915+
with pulse.build(backend=backend) as sched:
1916+
mem_slot = measure(0)
1917+
print(f"Qubit measured into {mem_slot}")
1918+
1919+
sched.draw()
1920+
17381921
Args:
17391922
func: The Python function to enable as a builder macro. There are no
17401923
requirements on the signature of the function, any calls to pulse
@@ -1827,6 +2010,19 @@ def measure_all() -> list[chans.MemorySlot]:
18272010
same time. This is useful for handling device ``meas_map`` and single
18282011
measurement constraints.
18292012
2013+
Examples:
2014+
2015+
.. code-block:: python
2016+
2017+
from qiskit import pulse
2018+
from qiskit.providers.fake_provider import FakeOpenPulse2Q
2019+
2020+
backend = FakeOpenPulse2Q()
2021+
2022+
with pulse.build(backend) as pulse_prog:
2023+
# Measure all qubits and return associated registers.
2024+
regs = pulse.measure_all()
2025+
18302026
.. note::
18312027
Requires the active builder context to have a backend set.
18322028
@@ -1855,6 +2051,19 @@ def delay_qubits(duration: int, *qubits: int):
18552051
r"""Insert delays on all the :class:`channels.Channel`\s that correspond
18562052
to the input ``qubits`` at the same time.
18572053
2054+
Examples:
2055+
2056+
.. code-block:: python
2057+
2058+
from qiskit import pulse
2059+
from qiskit.providers.fake_provider import FakeOpenPulse3Q
2060+
2061+
backend = FakeOpenPulse3Q()
2062+
2063+
with pulse.build(backend) as pulse_prog:
2064+
# Delay for 100 cycles on qubits 0, 1 and 2.
2065+
regs = pulse.delay_qubits(100, 0, 1, 2)
2066+
18582067
.. note:: Requires the active builder context to have a backend set.
18592068
18602069
Args:

test/python/compiler/test_transpiler.py

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989
from qiskit.transpiler.target import (
9090
InstructionProperties,
9191
Target,
92-
InstructionDurations,
9392
)
9493

9594
from test import QiskitTestCase, combine, slow_test # pylint: disable=wrong-import-order
@@ -1516,37 +1515,27 @@ def test_scheduling_instruction_constraints_backend(self):
15161515
"""Test that scheduling-related loose transpile constraints
15171516
work with BackendV2."""
15181517

1519-
with self.assertWarnsRegex(
1520-
DeprecationWarning,
1521-
expected_regex="argument ``calibrate_instructions`` is deprecated",
1522-
):
1523-
backend_v2 = GenericBackendV2(
1524-
2,
1525-
calibrate_instructions=True,
1526-
coupling_map=[[0, 1]],
1527-
basis_gates=["cx", "h"],
1528-
seed=0,
1529-
)
1518+
backend = GenericBackendV2(
1519+
2,
1520+
coupling_map=[[0, 1]],
1521+
basis_gates=["cx", "h"],
1522+
seed=42,
1523+
)
15301524
qc = QuantumCircuit(2)
15311525
qc.h(0)
1532-
qc.delay(500, 1, "dt")
1526+
qc.delay(0.000001, 1, "s")
15331527
qc.cx(0, 1)
1534-
# update durations
1535-
durations = InstructionDurations.from_backend(backend_v2)
1536-
durations.update([("cx", [0, 1], 1000, "dt")])
15371528

1538-
with self.assertWarnsRegex(
1539-
DeprecationWarning,
1540-
expected_regex="The `target` parameter should be used instead",
1541-
):
1542-
scheduled = transpile(
1543-
qc,
1544-
backend=backend_v2,
1545-
scheduling_method="alap",
1546-
instruction_durations=durations,
1547-
layout_method="trivial",
1548-
)
1549-
self.assertEqual(scheduled.duration, 1500)
1529+
# update cx to 2 seconds
1530+
backend.target.update_instruction_properties("cx", (0, 1), InstructionProperties(0.000001))
1531+
1532+
scheduled = transpile(
1533+
qc,
1534+
backend=backend,
1535+
scheduling_method="alap",
1536+
layout_method="trivial",
1537+
)
1538+
self.assertEqual(scheduled.duration, 9010)
15501539

15511540
def test_scheduling_instruction_constraints(self):
15521541
"""Test that scheduling-related loose transpile constraints work with target."""

0 commit comments

Comments
 (0)