diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index 80ad0b80..26fc3ff9 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -29,6 +29,7 @@ ) import numpy as np +from qiskit import transpile # type: ignore from qiskit.providers.aer.noise import NoiseModel # type: ignore from qiskit.quantum_info.operators import Pauli as qk_Pauli # type: ignore from qiskit.quantum_info.operators.symplectic.sparse_pauli_op import SparsePauliOp # type: ignore @@ -122,6 +123,7 @@ class _AerBaseBackend(Backend): _required_predicates: List[Predicate] _noise_model: Optional[NoiseModel] = None _has_arch: bool = False + _needs_transpile: bool = False @property def required_predicates(self) -> List[Predicate]: @@ -268,6 +270,9 @@ def process_circuits( qc.save_unitary() qcs.append(qc) + if self._needs_transpile: + qcs = transpile(qcs, self._qiskit_backend) + seed = cast(Optional[int], kwargs.get("seed")) job = self._qiskit_backend.run( qcs, @@ -584,6 +589,7 @@ class AerUnitaryBackend(_AerBaseBackend): _memory = False _noise_model = None + _needs_transpile = True _qiskit_backend_name = "aer_simulator_unitary" diff --git a/tests/backend_test.py b/tests/backend_test.py index 9b27aece..b55a5fd6 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -33,7 +33,7 @@ from qiskit_aer import Aer # type: ignore from qiskit_ibm_provider.exceptions import IBMError # type: ignore -from pytket.circuit import Circuit, OpType, BasisOrder, Qubit, reg_eq, Unitary2qBox # type: ignore +from pytket.circuit import Circuit, OpType, BasisOrder, Qubit, reg_eq, Unitary2qBox, QControlBox, CircBox # type: ignore from pytket.passes import CliffordSimp # type: ignore from pytket.pauli import Pauli, QubitPauliString # type: ignore from pytket.predicates import CompilationUnit, NoMidMeasurePredicate # type: ignore @@ -1374,3 +1374,24 @@ def test_unitary_sim_gateset() -> None: unitary_sim_gateset = backend.backend_info.gate_set unsupported_ops = {OpType.Reset, OpType.Measure, OpType.Conditional} assert unitary_sim_gateset.isdisjoint(unsupported_ops) + + +def test_unitary_backend_transpiles() -> None: + """regression test for https://github.com/CQCL/pytket-qiskit/issues/142""" + backend = AerUnitaryBackend() + n_ancillas = 5 # using n_ancillas <=4 doees not raise an error + n_spins = 1 + circ = Circuit(n_ancillas + n_spins) + trgt = Circuit(n_spins) + trgt.X(0) + + circ.add_qcontrolbox( + QControlBox(CircBox(trgt), n_ancillas), list(range(n_ancillas + n_spins)) + ) + + compiled_circ = backend.get_compiled_circuit(circ, optimisation_level=0) + # using optimisation_level >= 1 does not raise an error + r = backend.run_circuit(compiled_circ) + u = r.get_unitary() + # check that the lower-right 2x2 submatrix of the unitary is the matrix of the X gate. + assert np.isclose(u[62:64, 62:64], np.asarray(([0.0, 1.0], [1.0, 0.0]))).all()