From 4b8e578593da0ff01c6c4ab10b25aa269c484896 Mon Sep 17 00:00:00 2001 From: Jesus Talavera <145992175+jesus-talavera-ibm@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:17:44 +0200 Subject: [PATCH] chore: Fix tests after backend retirement (#91) --- README.md | 6 +- tests/ai/conftest.py | 4 +- tests/ai/test_permutation_ai.py | 32 +++--- tests/conftest.py | 163 ++++++++++++++++++++++++++++++- tests/test_transpiler_service.py | 10 +- 5 files changed, 185 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 8047a8f..0419e52 100644 --- a/README.md +++ b/README.md @@ -94,9 +94,9 @@ from qiskit_ibm_transpiler.ai.collection import CollectLinearFunctions from qiskit.circuit.library import EfficientSU2 ai_passmanager = PassManager([ - AIRouting(backend_name="ibm_cairo", optimization_level=3, layout_mode="optimize"), # Route circuit + AIRouting(backend_name="ibm_quebec", optimization_level=3, layout_mode="optimize"), # Route circuit CollectLinearFunctions(), # Collect Linear Function blocks - AILinearFunctionSynthesis(backend_name="ibm_cairo") # Re-synthesize Linear Function blocks + AILinearFunctionSynthesis(backend_name="ibm_quebec") # Re-synthesize Linear Function blocks ]) circuit = EfficientSU2(10, entanglement="full", reps=1).decompose() @@ -117,7 +117,7 @@ We expect to gradually increase the size of the supported blocks. All passes use a thread pool to send several requests in parallel. By default it will use as max threads as number of cores plus four (default values for `ThreadPoolExecutor` python object). However, you can set your own value with the `max_threads` argument at pass instantation. For example, the following line will instantiate the `AILinearFunctionSynthesis` pass allowing it to use a maximum of 20 threads. ```python -AILinearFunctionSynthesis(backend_name="ibm_cairo", max_threads=20) # Re-synthesize Linear Function blocks using 20 threads max +AILinearFunctionSynthesis(backend_name="ibm_quebec", max_threads=20) # Re-synthesize Linear Function blocks using 20 threads max ``` You can also set the environment variable `AI_TRANSPILER_MAX_THREADS` to the desired number of maximum threads, and all synthesis passes instantiated after that will use that value. diff --git a/tests/ai/conftest.py b/tests/ai/conftest.py index ac561b5..e331a1d 100644 --- a/tests/ai/conftest.py +++ b/tests/ai/conftest.py @@ -46,10 +46,10 @@ def create_linear_circuit(n_qubits, gates): @pytest.fixture(scope="module") -def random_circuit_transpiled(backend, cmap_backend): +def random_circuit_transpiled(backend_27q, cmap_backend): circuit = create_random_circuit(27, 4, 2) qiskit_lvl3_transpiler = generate_preset_pass_manager( - optimization_level=3, coupling_map=cmap_backend[backend] + optimization_level=3, coupling_map=cmap_backend[backend_27q] ) return qiskit_lvl3_transpiler.run(circuit) diff --git a/tests/ai/test_permutation_ai.py b/tests/ai/test_permutation_ai.py index 70ce882..cfffc44 100644 --- a/tests/ai/test_permutation_ai.py +++ b/tests/ai/test_permutation_ai.py @@ -21,8 +21,8 @@ @pytest.fixture -def permutations_circuit(backend, cmap_backend): - coupling_map = cmap_backend[backend] +def permutations_circuit(backend_27q, cmap_backend): + coupling_map = cmap_backend[backend_27q] cmap = list(coupling_map.get_edges()) orig_qc = QuantumCircuit(27) for i, j in cmap: @@ -64,11 +64,11 @@ def test_permutation_wrong_backend(caplog): @pytest.mark.skip( reason="Unreliable. It passes most of the times with the timeout of 1 second for the current circuits used" ) -def test_permutation_exceed_timeout(random_circuit_transpiled, backend, caplog): +def test_permutation_exceed_timeout(random_circuit_transpiled, backend_27q, caplog): ai_optimize_perm = PassManager( [ CollectPermutations(min_block_size=2, max_block_size=27), - AIPermutationSynthesis(backend_name=backend, timeout=1), + AIPermutationSynthesis(backend_name=backend_27q, timeout=1), ] ) ai_optimized_circuit = ai_optimize_perm.run(random_circuit_transpiled) @@ -80,11 +80,11 @@ def test_permutation_exceed_timeout(random_circuit_transpiled, backend, caplog): @pytest.mark.skip( reason="Unreliable many times. We'll research why it fails sporadically" ) -def test_permutation_wrong_token(random_circuit_transpiled, backend, caplog): +def test_permutation_wrong_token(random_circuit_transpiled, backend_27q, caplog): ai_optimize_perm = PassManager( [ CollectPermutations(min_block_size=2, max_block_size=27), - AIPermutationSynthesis(backend_name=backend, token="invented_token_2"), + AIPermutationSynthesis(backend_name=backend_27q, token="invented_token_2"), ] ) ai_optimized_circuit = ai_optimize_perm.run(random_circuit_transpiled) @@ -96,11 +96,13 @@ def test_permutation_wrong_token(random_circuit_transpiled, backend, caplog): reason="Unreliable many times. We'll research why it fails sporadically" ) @pytest.mark.disable_monkeypatch -def test_permutation_wrong_url(random_circuit_transpiled, backend): +def test_permutation_wrong_url(random_circuit_transpiled, backend_27q): ai_optimize_perm = PassManager( [ CollectPermutations(min_block_size=2, max_block_size=27), - AIPermutationSynthesis(backend_name=backend, base_url="https://ibm.com/"), + AIPermutationSynthesis( + backend_name=backend_27q, base_url="https://ibm.com/" + ), ] ) try: @@ -115,12 +117,12 @@ def test_permutation_wrong_url(random_circuit_transpiled, backend): reason="Unreliable many times. We'll research why it fails sporadically" ) @pytest.mark.disable_monkeypatch -def test_permutation_unexisting_url(random_circuit_transpiled, backend, caplog): +def test_permutation_unexisting_url(random_circuit_transpiled, backend_27q, caplog): ai_optimize_perm = PassManager( [ CollectPermutations(min_block_size=2, max_block_size=27), AIPermutationSynthesis( - backend_name=backend, + backend_name=backend_27q, base_url="https://invented-domain-qiskit-ibm-transpiler-123.com/", ), ] @@ -135,9 +137,9 @@ def test_permutation_unexisting_url(random_circuit_transpiled, backend, caplog): assert isinstance(ai_optimized_circuit, QuantumCircuit) -def test_permutation_collector(permutations_circuit, backend, cmap_backend): +def test_permutation_collector(permutations_circuit, backend_27q, cmap_backend): qiskit_lvl3_transpiler = generate_preset_pass_manager( - optimization_level=1, coupling_map=cmap_backend[backend] + optimization_level=1, coupling_map=cmap_backend[backend_27q] ) permutations_circuit = qiskit_lvl3_transpiler.run(permutations_circuit) @@ -158,14 +160,14 @@ def test_permutation_collector(permutations_circuit, backend, cmap_backend): assert not dag.named_nodes("clifford", "Clifford") -def test_permutation_pass(permutations_circuit, backend, caplog): +def test_permutation_pass(permutations_circuit, backend_27q, caplog): ai_optimize_perm = PassManager( [ CollectPermutations(max_block_size=27), - AIPermutationSynthesis(backend_name=backend), + AIPermutationSynthesis(backend_name=backend_27q), ] ) ai_optimized_circuit = ai_optimize_perm.run(permutations_circuit) - assert "Using the synthesized circuit" in caplog.text + assert "Requesting synthesis to the service" in caplog.text assert isinstance(ai_optimized_circuit, QuantumCircuit) diff --git a/tests/conftest.py b/tests/conftest.py index a53407c..0e0f09a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,7 +13,7 @@ import pytest from qiskit.transpiler.coupling import CouplingMap -from qiskit_ibm_runtime.fake_provider import FakeCairoV2 +from qiskit_ibm_runtime.fake_provider import FakeQuebec @pytest.fixture(autouse=True) @@ -44,18 +44,23 @@ def env_set(monkeypatch, request): @pytest.fixture(scope="module") def backend(): - return "ibm_cairo" + return "ibm_quebec" + + +@pytest.fixture(scope="module") +def backend_27q(): + return "ibm_peekskill" @pytest.fixture(scope="module") def coupling_map(): - return FakeCairoV2().coupling_map + return FakeQuebec().coupling_map @pytest.fixture(scope="module") def cmap_backend(): return { - "ibm_cairo": CouplingMap( + "ibm_peekskill": CouplingMap( [ [0, 1], [1, 0], @@ -114,5 +119,153 @@ def cmap_backend(): [25, 26], [26, 25], ] - ) + ), + "ibm_quebec": CouplingMap( + [ + [1, 0], + [2, 1], + [3, 2], + [3, 4], + [4, 15], + [5, 4], + [5, 6], + [6, 7], + [7, 8], + [8, 16], + [9, 8], + [9, 10], + [11, 10], + [11, 12], + [13, 12], + [14, 0], + [14, 18], + [16, 26], + [17, 12], + [19, 18], + [19, 20], + [20, 33], + [21, 20], + [21, 22], + [22, 15], + [23, 22], + [24, 23], + [25, 24], + [26, 25], + [26, 27], + [28, 27], + [28, 35], + [29, 28], + [30, 17], + [30, 29], + [31, 30], + [31, 32], + [34, 24], + [34, 43], + [35, 47], + [36, 32], + [38, 37], + [38, 39], + [39, 33], + [39, 40], + [40, 41], + [41, 42], + [43, 42], + [43, 44], + [44, 45], + [46, 45], + [47, 46], + [48, 47], + [48, 49], + [50, 49], + [51, 36], + [51, 50], + [52, 37], + [52, 56], + [53, 41], + [53, 60], + [54, 45], + [54, 64], + [55, 49], + [55, 68], + [57, 56], + [58, 57], + [58, 59], + [59, 60], + [60, 61], + [62, 61], + [62, 63], + [62, 72], + [64, 63], + [65, 64], + [65, 66], + [66, 67], + [66, 73], + [68, 67], + [69, 68], + [70, 69], + [70, 74], + [71, 58], + [71, 77], + [74, 89], + [75, 76], + [76, 77], + [77, 78], + [79, 78], + [80, 79], + [80, 81], + [81, 72], + [82, 81], + [82, 83], + [83, 84], + [85, 73], + [85, 84], + [85, 86], + [86, 87], + [87, 88], + [87, 93], + [89, 88], + [90, 75], + [91, 79], + [91, 98], + [92, 83], + [94, 90], + [94, 95], + [96, 95], + [96, 109], + [97, 96], + [97, 98], + [98, 99], + [100, 99], + [100, 110], + [101, 100], + [101, 102], + [102, 92], + [103, 102], + [103, 104], + [104, 105], + [106, 93], + [106, 105], + [106, 107], + [108, 107], + [108, 112], + [109, 114], + [110, 118], + [111, 104], + [114, 113], + [115, 114], + [115, 116], + [116, 117], + [118, 117], + [118, 119], + [120, 119], + [121, 120], + [122, 111], + [122, 121], + [123, 122], + [123, 124], + [124, 125], + [126, 112], + [126, 125], + ] + ), } diff --git a/tests/test_transpiler_service.py b/tests/test_transpiler_service.py index cad02d6..26cdca4 100644 --- a/tests/test_transpiler_service.py +++ b/tests/test_transpiler_service.py @@ -302,7 +302,7 @@ def test_transpile_malformed_body(): except Exception as e: assert ( str(e) - == "\"transpile() got an unexpected keyword argument 'failing_option'\"" + == "\"Error transpiling with Qiskit and qiskit_transpile_options: transpile() got an unexpected keyword argument 'failing_option'\"" ) @@ -377,20 +377,20 @@ def transpile_and_check_layout(cmap, circuit): compare_layouts(plugin_circ, non_ai_circ) -def test_layout_construction_no_service(backend, cmap_backend): +def test_layout_construction_no_service(backend_27q, cmap_backend): for n_qubits in [5, 10, 15, 20, 27]: circuit = random_circuit(n_qubits, 4, measure=True) - transpile_and_check_layout(cmap_backend[backend], circuit) + transpile_and_check_layout(cmap_backend[backend_27q], circuit) for n_qubits in [5, 10, 15, 20, 27]: circuit = EfficientSU2(n_qubits, entanglement="circular", reps=1).decompose() - transpile_and_check_layout(cmap_backend[backend], circuit) + transpile_and_check_layout(cmap_backend[backend_27q], circuit) for n_qubits in [5, 10, 15, 20, 27]: circuit = QuantumCircuit(n_qubits) circuit.cx(0, 1) circuit.cx(1, 2) circuit.h(4) - transpile_and_check_layout(cmap_backend[backend], circuit) + transpile_and_check_layout(cmap_backend[backend_27q], circuit) def test_fix_ecr_qasm2():