Skip to content

Commit

Permalink
Merge branch 'main' into EA/fix-windows
Browse files Browse the repository at this point in the history
  • Loading branch information
cbjuan authored Oct 8, 2024
2 parents cb4f85c + 4b8e578 commit fe26a43
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 30 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions tests/ai/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
32 changes: 17 additions & 15 deletions tests/ai/test_permutation_ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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:
Expand All @@ -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/",
),
]
Expand All @@ -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)

Expand All @@ -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)
163 changes: 158 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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],
]
),
}
10 changes: 5 additions & 5 deletions tests/test_transpiler_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'\""
)


Expand Down Expand Up @@ -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():
Expand Down

0 comments on commit fe26a43

Please sign in to comment.