diff --git a/qiskit/pulse/ir/ir.py b/qiskit/pulse/ir/ir.py index ccd5b88f4145..69588d4a34d6 100644 --- a/qiskit/pulse/ir/ir.py +++ b/qiskit/pulse/ir/ir.py @@ -242,7 +242,6 @@ def flatten(self, inplace: bool = False) -> SequenceIR: else: block = self.copy() - def edge_map(_x, _y, _node): if _y == _node: return 0 @@ -314,4 +313,16 @@ def __eq__(self, other: SequenceIR): # It is reasonable to assume that blocks with the same alignment and the same sequence # will result in the same time_table, but this decision should be made consciously. + def __deepcopy__(self, memo=None): + if memo is None: + memo = {} + copied = self.__class__(copy.deepcopy(self.alignment, memo=memo)) + memo[id(self)] = copied + copied._time_table = copy.copy(self._time_table) # Only int keys and values. + copied._sequence = copy.deepcopy(self._sequence, memo=memo) + # To ensure that copied object will be equal to the original. + copied._sequence[0] = self._InNode + copied._sequence[1] = self._OutNode + return copied + # TODO : __repr__ diff --git a/test/python/pulse/test_pulse_ir.py b/test/python/pulse/test_pulse_ir.py index c0cf84a1f174..0bcf2f926aa9 100644 --- a/test/python/pulse/test_pulse_ir.py +++ b/test/python/pulse/test_pulse_ir.py @@ -11,9 +11,11 @@ # that they have been altered from the originals. """Test pulse IR""" +import copy + from test import QiskitTestCase -from rustworkx import is_isomorphic_node_match from test.python.pulse.compiler_passes.utils import PulseIrTranspiler +from rustworkx import is_isomorphic_node_match from qiskit.pulse import ( Constant, @@ -504,7 +506,7 @@ def test_ir_equating_different_ordering(self): self.assertTrue(ir1 == ir2) - def test_ir_copy(self): + def test_ir_dedicated_copy(self): """Test the dedicated semi-deep copy method""" inst1 = Play(Constant(100, 0.5), frame=QubitFrame(1), target=Qubit(1)) inst2 = Play(Constant(100, 0.5), frame=QubitFrame(2), target=Qubit(2)) @@ -534,4 +536,34 @@ def test_ir_copy(self): self.assertIs(copied.elements()[1], inst2) self.assertIs(copied.elements()[0].elements()[0], inst1) + def test_ir_deepcopy(self): + """Test the deep copy method""" + inst1 = Play(Constant(100, 0.5), frame=QubitFrame(1), target=Qubit(1)) + inst2 = Play(Constant(100, 0.5), frame=QubitFrame(2), target=Qubit(2)) + block = SequenceIR(AlignRight()) + block.append(inst1) + ir1 = SequenceIR(AlignLeft()) + ir1.append(block) + ir1.append(inst2) + ir1.sequence.add_edge(0, 2, None) + ir1._time_table[3] = 100 + + copied = copy.deepcopy(ir1) + self.assertEqual(copied, ir1) + self.assertIsNot(copied, ir1) + self.assertEqual(copied.alignment, ir1.alignment) + self.assertEqual(copied._time_table, ir1._time_table) + self.assertIsNot(copied._time_table, ir1._time_table) + # PyDAG has no built-in equality check + self.assertTrue( + is_isomorphic_node_match(copied._sequence, ir1._sequence, lambda x, y: x == y) + ) + self.assertIsNot(copied._sequence, ir1._sequence) + self.assertEqual(copied.elements()[0], ir1.elements()[0]) + self.assertIsNot(copied.elements()[0], ir1.elements()[0]) + self.assertEqual(copied.elements()[1], inst2) + self.assertIsNot(copied.elements()[1], inst2) + self.assertEqual(copied.elements()[0].elements()[0], inst1) + self.assertIsNot(copied.elements()[0].elements()[0], inst1) + # TODO : Test SequenceIR.draw()