diff --git a/crates/accelerate/src/nlayout.rs b/crates/accelerate/src/nlayout.rs index 871d3696ddc..68dd8b3edc5 100644 --- a/crates/accelerate/src/nlayout.rs +++ b/crates/accelerate/src/nlayout.rs @@ -91,7 +91,7 @@ impl VirtualQubit { /// physical qubit index on the coupling graph. /// logical_qubits (int): The number of logical qubits in the layout /// physical_qubits (int): The number of physical qubits in the layout -#[pyclass(module = "qiskit._accelerate.stochastic_swap")] +#[pyclass(module = "qiskit._accelerate.nlayout")] #[derive(Clone, Debug)] pub struct NLayout { virt_to_phys: Vec, @@ -117,13 +117,12 @@ impl NLayout { res } - fn __getstate__(&self) -> (Vec, Vec) { - (self.virt_to_phys.clone(), self.phys_to_virt.clone()) - } - - fn __setstate__(&mut self, state: (Vec, Vec)) { - self.virt_to_phys = state.0; - self.phys_to_virt = state.1; + fn __reduce__(&self, py: Python) -> PyResult> { + Ok(( + py.get_type::().getattr("from_virtual_to_physical")?, + (self.virt_to_phys.to_object(py),), + ) + .into_py(py)) } /// Return the layout mapping. diff --git a/test/python/transpiler/test_layout.py b/test/python/transpiler/test_layout.py index 0847e78d646..00a7d879b52 100644 --- a/test/python/transpiler/test_layout.py +++ b/test/python/transpiler/test_layout.py @@ -13,12 +13,14 @@ """Tests the layout object""" import copy +import pickle import unittest import numpy from qiskit.circuit import QuantumRegister, Qubit from qiskit.transpiler.layout import Layout from qiskit.transpiler.exceptions import LayoutError +from qiskit._accelerate.nlayout import NLayout from test import QiskitTestCase # pylint: disable=wrong-import-order @@ -429,5 +431,54 @@ def test_layout_contains(self): self.assertNotIn(1, layout) +class TestNLayout(QiskitTestCase): + """This is a private class, so mostly doesn't need direct tests.""" + + def test_pickle(self): + """Test that the layout roundtrips through pickle.""" + v2p = [3, 5, 1, 2, 0, 4] + size = len(v2p) + layout = NLayout.from_virtual_to_physical(v2p) + self.assertEqual([layout.virtual_to_physical(x) for x in range(size)], v2p) + roundtripped = pickle.loads(pickle.dumps(layout)) + self.assertEqual([roundtripped.virtual_to_physical(x) for x in range(size)], v2p) + + # No changes to `layout`. + roundtripped.swap_virtual(0, 1) + expected = [5, 3, 1, 2, 0, 4] + self.assertEqual([layout.virtual_to_physical(x) for x in range(size)], v2p) + self.assertEqual([roundtripped.virtual_to_physical(x) for x in range(size)], expected) + + def test_copy(self): + """Test that the layout roundtrips through copy.""" + v2p = [3, 5, 1, 2, 0, 4] + size = len(v2p) + layout = NLayout.from_virtual_to_physical(v2p) + self.assertEqual([layout.virtual_to_physical(x) for x in range(size)], v2p) + roundtripped = copy.copy(layout) + self.assertEqual([roundtripped.virtual_to_physical(x) for x in range(size)], v2p) + + # No changes to `layout`. + roundtripped.swap_virtual(0, 1) + expected = [5, 3, 1, 2, 0, 4] + self.assertEqual([layout.virtual_to_physical(x) for x in range(size)], v2p) + self.assertEqual([roundtripped.virtual_to_physical(x) for x in range(size)], expected) + + def test_deepcopy(self): + """Test that the layout roundtrips through deepcopy.""" + v2p = [3, 5, 1, 2, 0, 4] + size = len(v2p) + layout = NLayout.from_virtual_to_physical(v2p) + self.assertEqual([layout.virtual_to_physical(x) for x in range(size)], v2p) + roundtripped = copy.deepcopy(layout) + self.assertEqual([roundtripped.virtual_to_physical(x) for x in range(size)], v2p) + + # No changes to `layout`. + roundtripped.swap_virtual(0, 1) + expected = [5, 3, 1, 2, 0, 4] + self.assertEqual([layout.virtual_to_physical(x) for x in range(size)], v2p) + self.assertEqual([roundtripped.virtual_to_physical(x) for x in range(size)], expected) + + if __name__ == "__main__": unittest.main()