diff --git a/qiskit_alice_bob_provider/remote/backend.py b/qiskit_alice_bob_provider/remote/backend.py index 41ffacc..829510a 100644 --- a/qiskit_alice_bob_provider/remote/backend.py +++ b/qiskit_alice_bob_provider/remote/backend.py @@ -45,6 +45,7 @@ def __init__(self, api_client: ApiClient, target_description: Dict): self._api_client = api_client self._target = ab_target_to_qiskit_target(target_description) self._options = _options_from_ab_target(target_description) + self._translation_plugin = _determine_translation_plugin(self._target) def __repr__(self) -> str: return f'' @@ -64,7 +65,7 @@ def max_circuits(self): def get_translation_stage_plugin(self): """This hook tells Qiskit to run the transpilation passes contained in translation_plugin.StatePreparationPlugin""" - return 'state_preparation' + return self._translation_plugin def run(self, run_input: QuantumCircuit, **kwargs) -> AliceBobRemoteJob: """Run the quantum circuit on the Alice & Bob backend by calling the @@ -131,3 +132,14 @@ def _ab_input_params_from_options(options: Options) -> Dict: name = 'nbShots' input_params[name] = value return input_params + + +def _determine_translation_plugin(target: Target) -> str: + """Choose which translation plugin to apply, depending on the gate set of + the backend.""" + instructions = {instr.name for instr, _ in target.instructions} + if any( + rotation in instructions for rotation in ['u', 'rx', 'ry', 'rz'] + ) or any(gate not in instructions for gate in ['h', 't']): + return 'state_preparation' + return 'sk_synthesis' diff --git a/tests/conftest.py b/tests/conftest.py index 561b420..0285ef2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -193,11 +193,61 @@ def all_instructions_target() -> dict: } +@pytest.fixture +def h_target() -> dict: + return { + 'name': 'H', + 'numQubits': 1, + 'instructions': [ + {'signature': '__quantum__qis__h__body:void (%Qubit*)'} + ], + 'inputParams': { + 'nbShots': { + 'required': True, + 'default': 1000, + 'constraints': [{'min': 1, 'max': 10000000}], + }, + 'averageNbPhotons': { + 'required': False, + 'default': None, + 'constraints': [], + }, + }, + } + + +@pytest.fixture +def h_t_target() -> dict: + return { + 'name': 'H_T', + 'numQubits': 1, + 'instructions': [ + {'signature': '__quantum__qis__h__body:void (%Qubit*)'}, + {'signature': '__quantum__qis__t__body:void (%Qubit*)'}, + ], + 'inputParams': { + 'nbShots': { + 'required': True, + 'default': 1000, + 'constraints': [{'min': 1, 'max': 10000000}], + }, + 'averageNbPhotons': { + 'required': False, + 'default': None, + 'constraints': [], + }, + }, + } + + @pytest.fixture def targets( - single_cat_target: Dict, all_instructions_target: Dict + single_cat_target: Dict, + all_instructions_target: Dict, + h_target: Dict, + h_t_target: Dict, ) -> List[Dict]: - return [single_cat_target, all_instructions_target] + return [single_cat_target, all_instructions_target, h_target, h_t_target] @pytest.fixture diff --git a/tests/remote/test_backend.py b/tests/remote/test_backend.py index c73384b..1e634d7 100644 --- a/tests/remote/test_backend.py +++ b/tests/remote/test_backend.py @@ -163,3 +163,30 @@ def test_translation_plugin_and_qir(mocked_targets) -> None: ) in qir ) + + +def test_determine_translation_plugin(mocked_targets) -> None: + p = AliceBobRemoteProvider(api_key='foo') + + # Rotations available + assert ( + p.get_backend('ALL_INSTRUCTIONS').get_translation_stage_plugin() + == 'state_preparation' + ) + + # H and T missing + assert ( + p.get_backend('EMU:1Q:LESCANNE_2020').get_translation_stage_plugin() + == 'state_preparation' + ) + + # T missing + assert ( + p.get_backend('H').get_translation_stage_plugin() + == 'state_preparation' + ) + + # ok + assert ( + p.get_backend('H_T').get_translation_stage_plugin() == 'sk_synthesis' + )