diff --git a/crates/accelerate/src/euler_one_qubit_decomposer.rs b/crates/accelerate/src/euler_one_qubit_decomposer.rs index 995d0e4810cb..1a30da570f93 100644 --- a/crates/accelerate/src/euler_one_qubit_decomposer.rs +++ b/crates/accelerate/src/euler_one_qubit_decomposer.rs @@ -34,7 +34,7 @@ enum SliceOrInt<'a> { Int(isize), } -#[pyclass] +#[pyclass(module = "qiskit._accelerate.euler_one_qubit_decomposer")] pub struct OneQubitGateErrorMap { error_map: Vec>, } @@ -50,9 +50,18 @@ impl OneQubitGateErrorMap { }, } } + fn add_qubit(&mut self, error_map: HashMap) { self.error_map.push(error_map); } + + fn __getstate__(&self) -> Vec> { + self.error_map.clone() + } + + fn __setstate__(&mut self, state: Vec>) { + self.error_map = state; + } } #[pyclass(sequence)] diff --git a/releasenotes/notes/fix-transpile-pickle-4045805b67c0c11b.yaml b/releasenotes/notes/fix-transpile-pickle-4045805b67c0c11b.yaml new file mode 100644 index 000000000000..7160cb7f9376 --- /dev/null +++ b/releasenotes/notes/fix-transpile-pickle-4045805b67c0c11b.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - Fix a bug in which running :class:`~.Optimize1qGatesDecomposition` + in parallel would raise an error due to OneQubitGateErrorMap + not being picklable. \ No newline at end of file diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py index 2f03fd5112b1..fe5670aba861 100644 --- a/test/python/compiler/test_transpiler.py +++ b/test/python/compiler/test_transpiler.py @@ -14,66 +14,71 @@ import copy import io +import math import os import sys -import math import unittest - from logging import StreamHandler, getLogger -from unittest.mock import patch - -from ddt import ddt, data, unpack from test import combine # pylint: disable=wrong-import-order +from unittest.mock import patch import numpy as np import rustworkx as rx - -from qiskit.exceptions import QiskitError -from qiskit import BasicAer -from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, pulse, qpy, qasm3 -from qiskit.circuit import Parameter, Gate, Qubit, Clbit, Reset -from qiskit.compiler import transpile -from qiskit.dagcircuit import DAGOutNode, DAGOpNode -from qiskit.converters import circuit_to_dag +from ddt import data, ddt, unpack + +from qiskit import BasicAer, ClassicalRegister, QuantumCircuit, QuantumRegister, pulse, qasm3, qpy +from qiskit.circuit import ( + Clbit, + ControlFlowOp, + ForLoopOp, + Gate, + IfElseOp, + Parameter, + Qubit, + Reset, + SwitchCaseOp, + WhileLoopOp, +) +from qiskit.circuit.delay import Delay from qiskit.circuit.library import ( CXGate, - U3Gate, - U2Gate, - U1Gate, + CZGate, + HGate, RXGate, RYGate, RZGate, + SXGate, + U1Gate, + U2Gate, + U3Gate, UGate, - CZGate, XGate, - SXGate, - HGate, ) -from qiskit.circuit import IfElseOp, WhileLoopOp, ForLoopOp, SwitchCaseOp, ControlFlowOp from qiskit.circuit.measure import Measure -from qiskit.circuit.delay import Delay -from qiskit.test import QiskitTestCase +from qiskit.compiler import transpile +from qiskit.converters import circuit_to_dag +from qiskit.dagcircuit import DAGOpNode, DAGOutNode +from qiskit.exceptions import QiskitError +from qiskit.providers.backend import BackendV2 from qiskit.providers.fake_provider import ( - FakeMelbourne, - FakeRueschlikon, FakeBoeblingen, + FakeMelbourne, FakeMumbaiV2, FakeNairobiV2, + FakeRueschlikon, FakeSherbrooke, ) -from qiskit.transpiler import Layout, CouplingMap -from qiskit.transpiler import PassManager, TransformationPass -from qiskit.transpiler.target import Target, InstructionProperties +from qiskit.providers.options import Options +from qiskit.pulse import InstructionScheduleMap +from qiskit.quantum_info import Operator, random_unitary +from qiskit.test import QiskitTestCase, slow_test +from qiskit.tools import parallel +from qiskit.transpiler import CouplingMap, Layout, PassManager, TransformationPass from qiskit.transpiler.exceptions import TranspilerError from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements, GateDirection -from qiskit.quantum_info import Operator, random_unitary from qiskit.transpiler.passmanager_config import PassManagerConfig -from qiskit.transpiler.preset_passmanagers import level_0_pass_manager -from qiskit.tools import parallel -from qiskit.pulse import InstructionScheduleMap -from qiskit.providers.backend import BackendV2 -from qiskit.providers.options import Options -from qiskit.test import slow_test +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager, level_0_pass_manager +from qiskit.transpiler.target import InstructionProperties, Target class CustomCX(Gate): @@ -1890,6 +1895,19 @@ def restore_default(): self.addCleanup(restore_default) parallel.PARALLEL_DEFAULT = True + @data(0, 1, 2, 3) + def test_parallel_multiprocessing(self, opt_level): + """Test parallel dispatch works with multiprocessing.""" + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0, 1) + qc.measure_all() + backend = FakeMumbaiV2() + pm = generate_preset_pass_manager(opt_level, backend) + res = pm.run([qc, qc]) + for circ in res: + self.assertIsInstance(circ, QuantumCircuit) + @data(0, 1, 2, 3) def test_parallel_with_target(self, opt_level): """Test that parallel dispatch works with a manual target.""" diff --git a/test/python/transpiler/test_optimize_1q_decomposition.py b/test/python/transpiler/test_optimize_1q_decomposition.py index f9b9759934c8..9f3cd3669afa 100644 --- a/test/python/transpiler/test_optimize_1q_decomposition.py +++ b/test/python/transpiler/test_optimize_1q_decomposition.py @@ -99,6 +99,15 @@ class TestOptimize1qGatesDecomposition(QiskitTestCase): """Test for 1q gate optimizations.""" + def test_run_pass_in_parallel(self): + """Test running pass on multiple circuits in parallel.""" + qr = QuantumRegister(1, "qr") + circuit = QuantumCircuit(qr) + passmanager = PassManager([Optimize1qGatesDecomposition(target=target_u1_u2_u3)]) + results = passmanager.run([circuit, circuit]) + for result in results: + self.assertTrue(Operator(circuit).equiv(Operator(result))) + @ddt.data(target_u1_u2_u3, target_rz_rx, target_rz_sx, target_rz_ry_u, target_h_p) def test_optimize_h_gates_target(self, target): """Transpile: qr:--[H]-[H]-[H]--"""