From ff816bff8ce3090a73782a81703a8e8f9099de5c Mon Sep 17 00:00:00 2001 From: Yaiza Date: Wed, 6 Nov 2024 17:40:01 +0100 Subject: [PATCH] WIP: Fixing tests --- qiskit_ibm_transpiler/ai/routing.py | 33 +++++++++++++++++++++++------ tests/ai/test_linear_function_ai.py | 29 ++++++++++++------------- tests/ai/test_permutation_ai.py | 27 +++++++++++------------ tests/ai/test_routing_ai.py | 20 ++++++++--------- 4 files changed, 62 insertions(+), 47 deletions(-) diff --git a/qiskit_ibm_transpiler/ai/routing.py b/qiskit_ibm_transpiler/ai/routing.py index a033058..cab4801 100644 --- a/qiskit_ibm_transpiler/ai/routing.py +++ b/qiskit_ibm_transpiler/ai/routing.py @@ -21,10 +21,16 @@ from qiskit.transpiler import CouplingMap, TranspilerError from qiskit.transpiler.basepasses import TransformationPass from qiskit.transpiler.layout import Layout +from qiskit.providers.backend import BackendV2 as Backend +from qiskit_ibm_runtime import QiskitRuntimeService from qiskit_ibm_transpiler.wrappers import AIRoutingAPI, AILocalRouting from typing import List, Union, Literal +import logging + +logger = logging.getLogger(__name__) + # TODO: Reuse this code, it's repeated several times OptimizationOptions = Literal["n_cnots", "n_gates", "cnot_layers", "layers", "noise"] @@ -48,6 +54,7 @@ class AIRouting(TransformationPass): def __init__( self, backend_name=None, + backend: Union[Backend, None] = None, coupling_map=None, optimization_level: int = 2, layout_mode: str = "OPTIMIZE", @@ -62,17 +69,25 @@ def __init__( local_mode: bool = True, **kwargs, ): + if backend_name: + # TODO: Updates with the final date + logger.warning( + "backend_name will be deprecated in February 2025, please use a backend object instead." + ) + super().__init__() routing_provider = AILocalRouting() if local_mode else AIRoutingAPI(**kwargs) - if backend_name is not None and coupling_map is not None: + if (backend_name or backend_name) and coupling_map: raise ValueError( f"ERROR. Both backend_name and coupling_map were specified as options. Please just use one of them." ) - if backend_name is not None: - self.backend = backend_name - elif coupling_map is not None: + + if not backend and not coupling_map and not backend_name: + raise ValueError(f"ERROR. Either backend OR coupling_map must be set.") + + if coupling_map: if isinstance(coupling_map, CouplingMap): self.backend = coupling_map elif isinstance(coupling_map, list): @@ -81,8 +96,14 @@ def __init__( raise ValueError( f"ERROR. coupling_map should either be a list of int tuples or a Qiskit CouplingMap object." ) - else: - raise ValueError(f"ERROR. Either backend_name OR coupling_map must be set.") + elif backend: + self.backend = backend + elif backend_name: + try: + runtime_service = QiskitRuntimeService() + self.backend = runtime_service.backend(name=backend_name) + except Exception: + raise PermissionError(f"ERROR. Backend not supported ({backend_name})") self.optimization_level = optimization_level self.optimization_preferences = optimization_preferences diff --git a/tests/ai/test_linear_function_ai.py b/tests/ai/test_linear_function_ai.py index 98748fd..43ccdb9 100644 --- a/tests/ai/test_linear_function_ai.py +++ b/tests/ai/test_linear_function_ai.py @@ -19,21 +19,20 @@ from qiskit_ibm_transpiler.ai.synthesis import AILinearFunctionSynthesis -def test_linear_function_wrong_backend(random_circuit_transpiled, caplog): - ai_optimize_lf = PassManager( - [ - CollectLinearFunctions(), - AILinearFunctionSynthesis(backend_name="wrong_backend", local_mode=False), - ] - ) - ai_optimized_circuit = ai_optimize_lf.run(random_circuit_transpiled) - assert "couldn't synthesize the circuit" in caplog.text - assert "Keeping the original circuit" in caplog.text - assert ( - "User doesn't have access to the specified backend: wrong_backend" - in caplog.text - ) - assert isinstance(ai_optimized_circuit, QuantumCircuit) +def test_linear_function_wrong_backend(random_circuit_transpiled): + with pytest.raises( + PermissionError, + match=r"ERROR. Backend not supported \(\w+\)", + ): + ai_linear_function_synthesis_pass = PassManager( + [ + CollectLinearFunctions(), + AILinearFunctionSynthesis( + backend_name="wrong_backend", local_mode=False + ), + ] + ) + ai_linear_function_synthesis_pass.run(random_circuit_transpiled) @pytest.mark.skip( diff --git a/tests/ai/test_permutation_ai.py b/tests/ai/test_permutation_ai.py index cfffc44..a32d735 100644 --- a/tests/ai/test_permutation_ai.py +++ b/tests/ai/test_permutation_ai.py @@ -40,25 +40,22 @@ def permutations_circuit(backend_27q, cmap_backend): return orig_qc -def test_permutation_wrong_backend(caplog): +def test_permutation_wrong_backend(): orig_qc = QuantumCircuit(3) orig_qc.swap(0, 1) orig_qc.swap(1, 2) - ai_optimize_perm = PassManager( - [ - CollectPermutations(min_block_size=2, max_block_size=27), - AIPermutationSynthesis(backend_name="wrong_backend"), - ] - ) - ai_optimized_circuit = ai_optimize_perm.run(orig_qc) - assert "couldn't synthesize the circuit" in caplog.text - assert "Keeping the original circuit" in caplog.text - assert ( - "User doesn't have access to the specified backend: wrong_backend" - in caplog.text - ) - assert isinstance(ai_optimized_circuit, QuantumCircuit) + with pytest.raises( + PermissionError, + match=r"ERROR. Backend not supported \(\w+\)", + ): + ai_permutation_synthesis_pass = PassManager( + [ + CollectPermutations(min_block_size=2, max_block_size=27), + AIPermutationSynthesis(backend_name="wrong_backend"), + ] + ) + ai_permutation_synthesis_pass.run(orig_qc) @pytest.mark.skip( diff --git a/tests/ai/test_routing_ai.py b/tests/ai/test_routing_ai.py index 9efa1d9..0defefc 100644 --- a/tests/ai/test_routing_ai.py +++ b/tests/ai/test_routing_ai.py @@ -49,18 +49,16 @@ def test_qv_routing_wrong_layout_mode(layout_mode, backend, qv_circ): def test_routing_wrong_backend(random_circuit_transpiled): - ai_optimize_lf = PassManager( - [ - AIRouting(backend_name="wrong_backend"), - ] - ) - try: - ai_optimized_circuit = ai_optimize_lf.run(random_circuit_transpiled) - pytest.fail("Error expected") - except Exception as e: - assert ( - "User doesn't have access to the specified backend: wrong_backend" in str(e) + with pytest.raises( + PermissionError, + match=r"ERROR. Backend not supported \(\w+\)", + ): + ai_routing_pass = PassManager( + [ + AIRouting(backend_name="wrong_backend"), + ] ) + ai_routing_pass.run(random_circuit_transpiled) @pytest.mark.skip(