mirror of https://github.com/Qiskit/qiskit.git
Fix pickling of `NLayout` (#12298)
Previously the module of this was set incorrectly (stemming from its move in gh-9064), at which point the `__getstate__`/`__setstate__` pickling wouldn't work correctly any more. Also, however, there was no `__getnewargs__` and `new` didn't have a zero-argument form, so this wouldn't have worked either.
This commit is contained in:
parent
686ff139a6
commit
136548c9d0
|
@ -91,7 +91,7 @@ impl VirtualQubit {
|
||||||
/// physical qubit index on the coupling graph.
|
/// physical qubit index on the coupling graph.
|
||||||
/// logical_qubits (int): The number of logical qubits in the layout
|
/// logical_qubits (int): The number of logical qubits in the layout
|
||||||
/// physical_qubits (int): The number of physical 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NLayout {
|
pub struct NLayout {
|
||||||
virt_to_phys: Vec<PhysicalQubit>,
|
virt_to_phys: Vec<PhysicalQubit>,
|
||||||
|
@ -117,13 +117,13 @@ impl NLayout {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __getstate__(&self) -> (Vec<PhysicalQubit>, Vec<VirtualQubit>) {
|
fn __reduce__(&self, py: Python) -> PyResult<Py<PyAny>> {
|
||||||
(self.virt_to_phys.clone(), self.phys_to_virt.clone())
|
Ok((
|
||||||
}
|
py.get_type_bound::<Self>()
|
||||||
|
.getattr("from_virtual_to_physical")?,
|
||||||
fn __setstate__(&mut self, state: (Vec<PhysicalQubit>, Vec<VirtualQubit>)) {
|
(self.virt_to_phys.to_object(py),),
|
||||||
self.virt_to_phys = state.0;
|
)
|
||||||
self.phys_to_virt = state.1;
|
.into_py(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the layout mapping.
|
/// Return the layout mapping.
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
"""Tests the layout object"""
|
"""Tests the layout object"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import pickle
|
||||||
import unittest
|
import unittest
|
||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
from qiskit.circuit import QuantumRegister, Qubit
|
from qiskit.circuit import QuantumRegister, Qubit
|
||||||
from qiskit.transpiler.layout import Layout
|
from qiskit.transpiler.layout import Layout
|
||||||
from qiskit.transpiler.exceptions import LayoutError
|
from qiskit.transpiler.exceptions import LayoutError
|
||||||
|
from qiskit._accelerate.nlayout import NLayout
|
||||||
from test import QiskitTestCase # pylint: disable=wrong-import-order
|
from test import QiskitTestCase # pylint: disable=wrong-import-order
|
||||||
|
|
||||||
|
|
||||||
|
@ -511,5 +513,54 @@ class LayoutTest(QiskitTestCase):
|
||||||
self.assertEqual(permutation, [1, 2, 0])
|
self.assertEqual(permutation, [1, 2, 0])
|
||||||
|
|
||||||
|
|
||||||
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue