diff --git a/circuit_knitting/cutting/qpd/instructions/qpd_gate.py b/circuit_knitting/cutting/qpd/instructions/qpd_gate.py index 7d2feac6e..555699d6b 100644 --- a/circuit_knitting/cutting/qpd/instructions/qpd_gate.py +++ b/circuit_knitting/cutting/qpd/instructions/qpd_gate.py @@ -201,6 +201,11 @@ def _define(self) -> None: qc.append(CircuitInstruction(op, [qc.qubits[0]], [])) self.definition = qc + @property + def _directive(self): + """``True`` if the ``basis_id`` is unassigned, which implies this instruction cannot be decomposed.""" + return self.basis_id is None + def __eq__(self, other): """Check equivalence for SingleQubitQPDGate class.""" return super().__eq__(other) and self.qubit_id == other.qubit_id diff --git a/test/cutting/test_cutting_workflows.py b/test/cutting/test_cutting_workflows.py new file mode 100644 index 000000000..b202c6ad0 --- /dev/null +++ b/test/cutting/test_cutting_workflows.py @@ -0,0 +1,50 @@ +# This code is a Qiskit project. + +# (C) Copyright IBM 2023. + +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Tests of various cutting workflows, particularly with regard to flexibility in transpilation.""" + +from copy import deepcopy + +from qiskit.circuit.library import EfficientSU2, CXGate +from qiskit.quantum_info import PauliList +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager +from qiskit.providers.fake_provider import FakeLagosV2 + +from circuit_knitting.cutting.qpd.instructions import SingleQubitQPDGate +from circuit_knitting.cutting.qpd import QPDBasis +from circuit_knitting.cutting import partition_problem + + +def test_transpile_before_realizing_basis_id(): + """Test a workflow where a :class:`.SingleQubitQPDGate` is passed through the transpiler.""" + circuit = EfficientSU2(4, entanglement="linear", reps=2).decompose() + circuit.assign_parameters([0.8] * len(circuit.parameters), inplace=True) + observables = PauliList(["ZZII"]) + subcircuits, bases, subobservables = partition_problem( + circuit=circuit, partition_labels="AABB", observables=observables + ) + + # Create a fake backend, and modify the target gate set so it thinks a + # SingleQubitQPDGate is allowed. + backend = FakeLagosV2() + target = deepcopy(backend.target) + sample_qpd_instruction = SingleQubitQPDGate(QPDBasis.from_gate(CXGate()), 1) + target.add_instruction( + sample_qpd_instruction, + {(i,): None for i in range(target.num_qubits)}, + ) + pass_manager = generate_preset_pass_manager(3, target=target) + + # Pass each subcircuit through the pass manager. + subcircuits = { + label: pass_manager.run(subcircuits["A"]) + for label, circuit in subcircuits.items() + }