Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix: ISA check to correctly map qubit indices inside blocks of control flow operations #1916

Merged
merged 5 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions qiskit_ibm_runtime/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def is_simulator(backend: BackendV1 | BackendV2) -> bool:
return getattr(backend, "simulator", False)


def _is_isa_circuit_helper(circuit: QuantumCircuit, target: Target) -> str:
def _is_isa_circuit_helper(circuit: QuantumCircuit, target: Target, qubit_map: Dict) -> str:
"""
A section of is_isa_circuit, separated to allow recursive calls
within blocks of conditional operations.
Expand All @@ -57,7 +57,7 @@ def _is_isa_circuit_helper(circuit: QuantumCircuit, target: Target) -> str:
operation = instruction.operation

name = operation.name
qargs = tuple(circuit.find_bit(x).index for x in instruction.qubits)
qargs = tuple(qubit_map[bit] for bit in instruction.qubits)
if (
not target.instruction_supported(name, qargs)
and name != "barrier"
Expand All @@ -69,7 +69,7 @@ def _is_isa_circuit_helper(circuit: QuantumCircuit, target: Target) -> str:

if isinstance(operation, ControlFlowOp):
for sub_circ in operation.blocks:
sub_string = _is_isa_circuit_helper(sub_circ, target)
sub_string = _is_isa_circuit_helper(sub_circ, target, qubit_map)
if sub_string:
return sub_string

Expand All @@ -93,7 +93,8 @@ def is_isa_circuit(circuit: QuantumCircuit, target: Target) -> str:
f"but the target system requires {target.num_qubits} qubits."
)

return _is_isa_circuit_helper(circuit, target)
qubit_map = {qubit: index for index, qubit in enumerate(circuit.qubits)}
return _is_isa_circuit_helper(circuit, target, qubit_map)


def are_circuits_dynamic(circuits: List[QuantumCircuit], qasm_default: bool = True) -> bool:
Expand Down
21 changes: 20 additions & 1 deletion test/unit/test_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from qiskit.primitives.containers.sampler_pub import SamplerPub
from qiskit.circuit.library import RealAmplitudes
from qiskit_ibm_runtime import Session, SamplerV2, SamplerOptions, IBMInputValueError
from qiskit_ibm_runtime.fake_provider import FakeFractionalBackend, FakeSherbrooke
from qiskit_ibm_runtime.fake_provider import FakeFractionalBackend, FakeSherbrooke, FakeCusco

from ..ibm_test_case import IBMTestCase
from ..utils import MockSession, dict_paritally_equal, get_mocked_backend, transpile_pubs
Expand Down Expand Up @@ -241,3 +241,22 @@ def test_gate_not_in_target(self):

with self.assertRaisesRegex(IBMInputValueError, " h "):
sampler.run(pubs=[(circ)])

@data(FakeSherbrooke(), FakeCusco())
def test_isa_inside_condition_block(self, backend):
"""Test no exception for 2q gates involving qubits that are not connected in
the coupling map, inside control operation blocks; and yes exception for
qubit pairs that are not connected"""
# pylint: disable=invalid-name,not-context-manager

circ = QuantumCircuit(5, 1)
circ.x(0)
circ.measure(0, 0)
with circ.if_test((0, 1)):
circ.ecr(1, 2)

if backend.name == "fake_sherbrooke":
SamplerV2(backend).run(pubs=[(circ)])
else:
with self.assertRaises(IBMInputValueError):
SamplerV2(backend).run(pubs=[(circ)])