diff --git a/test/python/pulse/test_builder.py b/test/python/pulse/test_builder.py index 1d7f09d5df78..62351df8abe2 100644 --- a/test/python/pulse/test_builder.py +++ b/test/python/pulse/test_builder.py @@ -21,7 +21,7 @@ from qiskit.pulse.instructions import directives from qiskit.pulse.transforms import target_qobj_transform from qiskit.test import QiskitTestCase -from qiskit.providers.fake_provider import FakeOpenPulse2Q +from qiskit.providers.fake_provider import FakeOpenPulse2Q, FakeMumbaiV2 from qiskit.providers.fake_provider.utils.configurable_backend import ( ConfigurableFakeBackend as ConfigurableBackend, ) @@ -29,7 +29,7 @@ class TestBuilder(QiskitTestCase): - """Test the pulse builder context.""" + """Test the pulse builder context with backendV1.""" def setUp(self): super().setUp() @@ -46,6 +46,14 @@ def assertScheduleEqual(self, program, target): self.assertEqual(target_qobj_transform(program), target_qobj_transform(target)) +class TestBuilderV2(QiskitTestCase): + """Test the pulse builder context with backendV1.""" + + def setUp(self): + super().setUp() + self.backend = FakeMumbaiV2() + + class TestBuilderBase(TestBuilder): """Test builder base.""" @@ -258,7 +266,6 @@ def test_phase_compensated_frequency_offset(self): """Test that the phase offset context properly compensates for phase accumulation.""" d0 = pulse.DriveChannel(0) - with pulse.build(self.backend) as schedule: with pulse.frequency_offset(1e9, d0, compensate_phase=True): pulse.delay(10, d0) @@ -270,7 +277,6 @@ def test_phase_compensated_frequency_offset(self): -2 * np.pi * ((1e9 * 10 * self.configuration.dt) % 1), d0 ) reference += instructions.ShiftFrequency(-1e9, d0) - self.assertScheduleEqual(schedule, reference) @@ -535,7 +541,6 @@ def test_barrier_on_qubits(self): """Test barrier directive on qubits.""" with pulse.build(self.backend) as schedule: pulse.barrier(0, 1) - reference = pulse.ScheduleBlock() reference += directives.RelativeBarrier( pulse.DriveChannel(0), @@ -1208,3 +1213,186 @@ def test_call_subroutine_with_parametrized_duration(self): pulse.call(subroutine) self.assertEqual(len(main.blocks), 1) + + +class TestBuilderBaseV2(TestBuilderV2, TestBuilderBase): + """Test builder base with backendV2.""" + + +class TestContextsV2(TestBuilderV2, TestContexts): + """Test builder contexts with backendV2.""" + + def test_phase_compensated_frequency_offset(self): + """Test that the phase offset context properly compensates for phase + accumulation with backendV2.""" + d0 = pulse.DriveChannel(0) + with pulse.build(self.backend) as schedule: + with pulse.frequency_offset(1e9, d0, compensate_phase=True): + pulse.delay(10, d0) + + reference = pulse.Schedule() + reference += instructions.ShiftFrequency(1e9, d0) + reference += instructions.Delay(10, d0) + reference += instructions.ShiftPhase( + -2 * np.pi * ((1e9 * 10 * self.backend.target.dt) % 1), d0 + ) + reference += instructions.ShiftFrequency(-1e9, d0) + self.assertScheduleEqual(schedule, reference) + + +class TestChannelsV2(TestBuilderV2, TestChannels): + """Test builder channels with backendV2.""" + + +class TestInstructionsV2(TestBuilderV2, TestInstructions): + """Test builder instructions with backendV2.""" + + +class TestDirectivesV2(TestBuilderV2, TestDirectives): + """Test builder directives with backendV2..""" + + def test_barrier_on_qubits(self): + """Test barrier directive on qubits with backendV2. + A part of qubits map of Mumbai + 0 -- 1 -- 4 -- + | + | + 2 + """ + with pulse.build(self.backend) as schedule: + pulse.barrier(0, 1) + reference = pulse.ScheduleBlock() + reference += directives.RelativeBarrier( + pulse.DriveChannel(0), + pulse.DriveChannel(1), + pulse.MeasureChannel(0), + pulse.MeasureChannel(1), + pulse.ControlChannel(0), + pulse.ControlChannel(1), + pulse.ControlChannel(2), + pulse.ControlChannel(3), + pulse.ControlChannel(4), + pulse.ControlChannel(8), + pulse.AcquireChannel(0), + pulse.AcquireChannel(1), + ) + self.assertEqual(schedule, reference) + + +class TestUtilitiesV2(TestBuilderV2, TestUtilities): + """Test builder utilities with backendV2.""" + + def test_num_qubits(self): + """Test builder utility to get number of qubits with backendV2.""" + with pulse.build(self.backend): + self.assertEqual(pulse.num_qubits(), 27) + + def test_samples_to_seconds(self): + """Test samples to time with backendV2""" + target = self.backend.target + target.dt = 0.1 + with pulse.build(self.backend): + time = pulse.samples_to_seconds(100) + self.assertTrue(isinstance(time, float)) + self.assertEqual(pulse.samples_to_seconds(100), 10) + + def test_samples_to_seconds_array(self): + """Test samples to time (array format) with backendV2.""" + target = self.backend.target + target.dt = 0.1 + with pulse.build(self.backend): + samples = np.array([100, 200, 300]) + times = pulse.samples_to_seconds(samples) + self.assertTrue(np.issubdtype(times.dtype, np.floating)) + np.testing.assert_allclose(times, np.array([10, 20, 30])) + + def test_seconds_to_samples(self): + """Test time to samples with backendV2""" + target = self.backend.target + target.dt = 0.1 + with pulse.build(self.backend): + samples = pulse.seconds_to_samples(10) + self.assertTrue(isinstance(samples, int)) + self.assertEqual(pulse.seconds_to_samples(10), 100) + + def test_seconds_to_samples_array(self): + """Test time to samples (array format) with backendV2.""" + target = self.backend.target + target.dt = 0.1 + with pulse.build(self.backend): + times = np.array([10, 20, 30]) + samples = pulse.seconds_to_samples(times) + self.assertTrue(np.issubdtype(samples.dtype, np.integer)) + np.testing.assert_allclose(pulse.seconds_to_samples(times), np.array([100, 200, 300])) + + +class TestMacrosV2(TestBuilderV2, TestMacros): + """Test builder macros with backendV2.""" + + def test_measure(self): + """Test utility function - measure with backendV2.""" + with pulse.build(self.backend) as schedule: + reg = pulse.measure(0) + + self.assertEqual(reg, pulse.MemorySlot(0)) + + reference = macros.measure(qubits=[0], backend=self.backend, meas_map=self.backend.meas_map) + + self.assertScheduleEqual(schedule, reference) + + def test_measure_multi_qubits(self): + """Test utility function - measure with multi qubits with backendV2.""" + with pulse.build(self.backend) as schedule: + regs = pulse.measure([0, 1]) + + self.assertListEqual(regs, [pulse.MemorySlot(0), pulse.MemorySlot(1)]) + + reference = macros.measure( + qubits=[0, 1], backend=self.backend, meas_map=self.backend.meas_map + ) + + self.assertScheduleEqual(schedule, reference) + + def test_measure_all(self): + """Test utility function - measure with backendV2..""" + with pulse.build(self.backend) as schedule: + regs = pulse.measure_all() + + self.assertEqual(regs, [pulse.MemorySlot(i) for i in range(self.backend.num_qubits)]) + reference = macros.measure_all(self.backend) + + self.assertScheduleEqual(schedule, reference) + + def test_delay_qubits(self): + """Test delaying on multiple qubits with backendV2 to make sure we don't insert delays twice.""" + with pulse.build(self.backend) as schedule: + pulse.delay_qubits(10, 0, 1) + + d0 = pulse.DriveChannel(0) + d1 = pulse.DriveChannel(1) + m0 = pulse.MeasureChannel(0) + m1 = pulse.MeasureChannel(1) + a0 = pulse.AcquireChannel(0) + a1 = pulse.AcquireChannel(1) + u0 = pulse.ControlChannel(0) + u1 = pulse.ControlChannel(1) + u2 = pulse.ControlChannel(2) + u3 = pulse.ControlChannel(3) + u4 = pulse.ControlChannel(4) + u8 = pulse.ControlChannel(8) + + reference = pulse.Schedule() + reference += instructions.Delay(10, d0) + reference += instructions.Delay(10, d1) + reference += instructions.Delay(10, m0) + reference += instructions.Delay(10, m1) + reference += instructions.Delay(10, a0) + reference += instructions.Delay(10, a1) + reference += instructions.Delay(10, u0) + reference += instructions.Delay(10, u1) + reference += instructions.Delay(10, u2) + reference += instructions.Delay(10, u3) + reference += instructions.Delay(10, u4) + reference += instructions.Delay(10, u8) + + self.assertScheduleEqual(schedule, reference)