From f43ec8e75ba7c655596a515c620c862f7fc91e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= <57907331+ElePT@users.noreply.github.com> Date: Fri, 30 Aug 2024 21:10:26 +0200 Subject: [PATCH 1/2] Fix use of `node.op` in `Split2QUnitaries` (#13015) * Replace node.op with node.matrix * Add docstring to test gate * Fix black (cherry picked from commit 623415cdb740fd6e164f0f5fd2b55fba081cd437) --- .../passes/optimization/split_2q_unitaries.py | 2 +- ...nitaries-custom-gate-d10f7670a35548f4.yaml | 6 +++ .../transpiler/test_split_2q_unitaries.py | 39 ++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/fix-split-2q-unitaries-custom-gate-d10f7670a35548f4.yaml diff --git a/qiskit/transpiler/passes/optimization/split_2q_unitaries.py b/qiskit/transpiler/passes/optimization/split_2q_unitaries.py index 7508c9440a6e..808bd51059ee 100644 --- a/qiskit/transpiler/passes/optimization/split_2q_unitaries.py +++ b/qiskit/transpiler/passes/optimization/split_2q_unitaries.py @@ -50,7 +50,7 @@ def run(self, dag: DAGCircuit): ): continue - decomp = TwoQubitWeylDecomposition(node.op, fidelity=self.requested_fidelity) + decomp = TwoQubitWeylDecomposition(node.matrix, fidelity=self.requested_fidelity) if ( decomp._inner_decomposition.specialization == TwoQubitWeylDecomposition._specializations.IdEquiv diff --git a/releasenotes/notes/fix-split-2q-unitaries-custom-gate-d10f7670a35548f4.yaml b/releasenotes/notes/fix-split-2q-unitaries-custom-gate-d10f7670a35548f4.yaml new file mode 100644 index 000000000000..331156cf6012 --- /dev/null +++ b/releasenotes/notes/fix-split-2q-unitaries-custom-gate-d10f7670a35548f4.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixed a bug in :class:`.Split2QUnitaries` where it would fail to run on circuits + with custom gates that didn't implement :meth:`__array__`. + See `#12984 `__. \ No newline at end of file diff --git a/test/python/transpiler/test_split_2q_unitaries.py b/test/python/transpiler/test_split_2q_unitaries.py index 616d93e5b3f8..7fbb93c2419d 100644 --- a/test/python/transpiler/test_split_2q_unitaries.py +++ b/test/python/transpiler/test_split_2q_unitaries.py @@ -19,7 +19,7 @@ from qiskit import QuantumCircuit, QuantumRegister, transpile from qiskit.circuit.library import UnitaryGate, XGate, ZGate, HGate -from qiskit.circuit import Parameter, CircuitInstruction +from qiskit.circuit import Parameter, CircuitInstruction, Gate from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.quantum_info import Operator from qiskit.transpiler import PassManager @@ -223,3 +223,40 @@ def test_split_qft(self): pm.append(Split2QUnitaries()) qc_split = pm.run(qc) self.assertEqual(26, qc_split.num_nonlocal_gates()) + + def test_gate_no_array(self): + """ + Test that the pass doesn't fail when the circuit contains a custom gate + with no ``__array__`` implementation. + + Reproduce from: https://github.com/Qiskit/qiskit/issues/12970 + """ + + class MyGate(Gate): + """Custom gate""" + + def __init__(self): + super().__init__("mygate", 2, []) + + def to_matrix(self): + return np.eye(4, dtype=complex) + # return np.eye(4, dtype=float) + + def mygate(self, qubit1, qubit2): + return self.append(MyGate(), [qubit1, qubit2], []) + + QuantumCircuit.mygate = mygate + + qc = QuantumCircuit(2) + qc.mygate(0, 1) + + pm = PassManager() + pm.append(Collect2qBlocks()) + pm.append(ConsolidateBlocks()) + pm.append(Split2QUnitaries()) + qc_split = pm.run(qc) + + self.assertTrue(Operator(qc).equiv(qc_split)) + self.assertTrue( + matrix_equal(Operator(qc).data, Operator(qc_split).data, ignore_phase=False) + ) From eac3f39a622360187bc33ea0d4e1142ef6a31899 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 30 Aug 2024 16:18:21 -0400 Subject: [PATCH 2/2] Update test/python/transpiler/test_split_2q_unitaries.py --- test/python/transpiler/test_split_2q_unitaries.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/python/transpiler/test_split_2q_unitaries.py b/test/python/transpiler/test_split_2q_unitaries.py index 7fbb93c2419d..adedb2106ab8 100644 --- a/test/python/transpiler/test_split_2q_unitaries.py +++ b/test/python/transpiler/test_split_2q_unitaries.py @@ -240,7 +240,6 @@ def __init__(self): def to_matrix(self): return np.eye(4, dtype=complex) - # return np.eye(4, dtype=float) def mygate(self, qubit1, qubit2): return self.append(MyGate(), [qubit1, qubit2], [])