diff --git a/qiskit/pulse/compiler/basepasses.py b/qiskit/pulse/compiler/basepasses.py index 8e1c40443ae..e362935c181 100644 --- a/qiskit/pulse/compiler/basepasses.py +++ b/qiskit/pulse/compiler/basepasses.py @@ -46,6 +46,16 @@ def run( ) -> IrBlock: pass + def __hash__(self) -> int: + warnings.warn( + f"{self.__class__} does not explicitly define a protocol to calculate hash. " + "This pass created the hash only by considering the class name. " + "Qiskit flow controller assumes passes with the identical hash are idempotent, " + "and it may skip execution of the other passes in the pipeline.", + RuntimeWarning, + ) + return hash((self.__class__.__name__,)) + def __eq__(self, other): warnings.warn( f"{self.__class__} does not explicitly define a protocol to evaluate equality. " @@ -83,6 +93,16 @@ def run( ) -> None: pass + def __hash__(self) -> int: + warnings.warn( + f"{self.__class__} does not explicitly define a protocol to calculate hash. " + "This pass created the hash only by considering the class name. " + "Qiskit flow controller assumes passes with the identical hash are idempotent, " + "and it may skip execution of the other passes in the pipeline.", + RuntimeWarning, + ) + return hash((self.__class__.__name__,)) + def __eq__(self, other): warnings.warn( f"{self.__class__} does not explicitly define a protocol to evaluate equality. " diff --git a/qiskit/pulse/compiler/passmanager.py b/qiskit/pulse/compiler/passmanager.py index b86f36963dd..6179a201bcc 100644 --- a/qiskit/pulse/compiler/passmanager.py +++ b/qiskit/pulse/compiler/passmanager.py @@ -55,11 +55,12 @@ def _passmanager_frontend( ) -> IrBlock: def _wrap_recursive(_prog): - _ret = IrBlock(alignment=input_program.alignment_context) + _ret = IrBlock(alignment=_prog.alignment_context) for _elm in _prog.blocks: if isinstance(_elm, ScheduleBlock): - return _wrap_recursive(_elm) - _ret.add_element(IrInstruction(instruction=_elm)) + _ret.add_element(_wrap_recursive(_elm)) + else: + _ret.add_element(IrInstruction(instruction=_elm)) return _ret return _wrap_recursive(input_program) @@ -148,11 +149,12 @@ def _passmanager_backend( ) -> ScheduleBlock: def _unwrap_recursive(_prog): - _ret = ScheduleBlock(alignment_context=passmanager_ir.alignment) + _ret = ScheduleBlock(alignment_context=_prog.alignment) for _elm in _prog.elements: if isinstance(_elm, IrBlock): - return _unwrap_recursive(_elm) - _ret.append(_elm.instruction, inplace=True) + _ret.append(_unwrap_recursive(_elm), inplace=True) + else: + _ret.append(_elm.instruction, inplace=True) return _ret out_block = _unwrap_recursive(passmanager_ir) diff --git a/test/python/pulse/test_compile.py b/test/python/pulse/test_compile.py index 697cbd3b5a5..c0464e1f03c 100644 --- a/test/python/pulse/test_compile.py +++ b/test/python/pulse/test_compile.py @@ -13,18 +13,35 @@ """A test cases for pulse compilation.""" from qiskit.pulse.compiler import BlockTranspiler +from qiskit.pulse.compiler.basepasses import TransformationPass +from qiskit.pulse.ir.ir import IrBlock +from qiskit.providers.fake_provider import GenericBackendV2 from test import QiskitTestCase # pylint: disable=wrong-import-order from . import _dummy_programs as schedule_lib +class _DummyPass(TransformationPass): + """A test pass that doesn't perform any transformation.""" + + def run(self, passmanager_ir: IrBlock) -> IrBlock: + return passmanager_ir + + def __hash__(self) -> int: + return hash((self.__class__.__name__,)) + + def __eq__(self, other): + return self.__class__.__name == other.__class__.name__ + + class TestCompiler(QiskitTestCase): """Test case for pulse compiler.""" def test_roundtrip_simple(self): """Test just returns the input program.""" # Just convert an input to PulseIR and convert it back to ScheduleBlock. - pm = BlockTranspiler() + backend = GenericBackendV2(2) + pm = BlockTranspiler([_DummyPass(backend.target)]) in_prog = schedule_lib.play_gaussian() out_prog = pm.run(pulse_programs=in_prog) @@ -33,7 +50,8 @@ def test_roundtrip_simple(self): def test_roundtrip_nested(self): """Test just returns the input program.""" # Just convert an input to PulseIR and convert it back to ScheduleBlock. - pm = BlockTranspiler() + backend = GenericBackendV2(2) + pm = BlockTranspiler([_DummyPass(backend.target)]) in_prog = schedule_lib.play_and_inner_block_sequential() out_prog = pm.run(pulse_programs=in_prog)