From 5a1f73e874636c12b24b3b8eac70085e792f4730 Mon Sep 17 00:00:00 2001 From: chrisamirani Date: Mon, 24 Jun 2024 12:18:16 -0700 Subject: [PATCH 1/5] Correctly parse string boolean for ai param --- qiskit_transpiler_service/wrappers/transpile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qiskit_transpiler_service/wrappers/transpile.py b/qiskit_transpiler_service/wrappers/transpile.py index d3014a4..80dfc08 100644 --- a/qiskit_transpiler_service/wrappers/transpile.py +++ b/qiskit_transpiler_service/wrappers/transpile.py @@ -59,11 +59,13 @@ def transpile( json_args["qiskit_transpile_options"] = qiskit_transpile_options if coupling_map is not None: json_args["backend_coupling_map"] = coupling_map + + ai_param = 'true' if ai else 'false' params = { "backend": backend, "optimization_level": optimization_level, - "ai": ai, + "ai": ai_param, } if ai_layout_mode is not None: From 697d9ef48d517f4eb3fb9237a00cb9b7092bb166 Mon Sep 17 00:00:00 2001 From: chrisamirani Date: Wed, 26 Jun 2024 16:03:26 -0700 Subject: [PATCH 2/5] User literal values in argument for ai --- qiskit_transpiler_service/transpiler_service.py | 8 ++++---- qiskit_transpiler_service/wrappers/transpile.py | 8 +++----- tests/test_transpiler_service.py | 12 ++++++------ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/qiskit_transpiler_service/transpiler_service.py b/qiskit_transpiler_service/transpiler_service.py index ac98514..9741123 100644 --- a/qiskit_transpiler_service/transpiler_service.py +++ b/qiskit_transpiler_service/transpiler_service.py @@ -27,7 +27,7 @@ """ import logging -from typing import Dict, List, Union +from typing import Dict, List, Union, Literal from qiskit import QuantumCircuit @@ -42,8 +42,8 @@ class TranspilerService: :param optimization_level: The optimization level to use during the transpilation. There are 4 optimization levels ranging from 0 to 3, where 0 is intended for not performing any optimizations and 3 spends the most effort to optimize the circuit. :type optimization_level: int - :param ai: Specifyies if the transpilation should use AI or not, defaults to True. - :type ai: bool, optional + :param ai: Specifies if the transpilation should use AI or not, defaults to True. + :type ai: str, optional :param coupling_map: A list of pairs that represents physical links between qubits. :type coupling_map: list[list[int]], optional :param backend_name: Name of the backend used for doing the transpilation. @@ -57,7 +57,7 @@ class TranspilerService: def __init__( self, optimization_level: int, - ai: bool = True, + ai: Literal['true', 'false', 'auto'] = 'true', coupling_map: Union[List[List[int]], None] = None, backend_name: Union[str, None] = None, qiskit_transpile_options: Dict = None, diff --git a/qiskit_transpiler_service/wrappers/transpile.py b/qiskit_transpiler_service/wrappers/transpile.py index 80dfc08..053b126 100644 --- a/qiskit_transpiler_service/wrappers/transpile.py +++ b/qiskit_transpiler_service/wrappers/transpile.py @@ -11,7 +11,7 @@ # that they have been altered from the originals. import logging -from typing import Dict, List, Union +from typing import Dict, List, Union, Literal import numpy as np from qiskit import QuantumCircuit, QuantumRegister, qasm2, qasm3 @@ -43,7 +43,7 @@ def transpile( optimization_level: int = 1, backend: Union[str, None] = None, coupling_map: Union[List[List[int]], None] = None, - ai: bool = True, + ai: Literal['true', 'false', 'auto'] = 'true', qiskit_transpile_options: Dict = None, ai_layout_mode: str = None, ): @@ -59,13 +59,11 @@ def transpile( json_args["qiskit_transpile_options"] = qiskit_transpile_options if coupling_map is not None: json_args["backend_coupling_map"] = coupling_map - - ai_param = 'true' if ai else 'false' params = { "backend": backend, "optimization_level": optimization_level, - "ai": ai_param, + "ai": ai, } if ai_layout_mode is not None: diff --git a/tests/test_transpiler_service.py b/tests/test_transpiler_service.py index fc8af7f..4661ab0 100644 --- a/tests/test_transpiler_service.py +++ b/tests/test_transpiler_service.py @@ -32,7 +32,7 @@ @pytest.mark.parametrize( "optimization_level", [1, 2, 3], ids=["opt_level_1", "opt_level_2", "opt_level_3"] ) -@pytest.mark.parametrize("ai", [False, True], ids=["no_ai", "ai"]) +@pytest.mark.parametrize("ai", ['false', 'true'], ids=["no_ai", "ai"]) @pytest.mark.parametrize( "qiskit_transpile_options", [None, {"seed_transpiler": 0}], @@ -56,7 +56,7 @@ def test_rand_circ_backend_routing(optimization_level, ai, qiskit_transpile_opti @pytest.mark.parametrize( "optimization_level", [1, 2, 3], ids=["opt_level_1", "opt_level_2", "opt_level_3"] ) -@pytest.mark.parametrize("ai", [False, True], ids=["no_ai", "ai"]) +@pytest.mark.parametrize("ai", ['false', 'true'], ids=["no_ai", "ai"]) @pytest.mark.parametrize( "qiskit_transpile_options", [None, {"seed_transpiler": 0}], @@ -85,7 +85,7 @@ def test_qv_backend_routing(optimization_level, ai, qiskit_transpile_options): ], ) @pytest.mark.parametrize("optimization_level", [1, 2, 3]) -@pytest.mark.parametrize("ai", [False, True], ids=["no_ai", "ai"]) +@pytest.mark.parametrize("ai", ['false', 'true'], ids=["no_ai", "ai"]) @pytest.mark.parametrize("qiskit_transpile_options", [None, {"seed_transpiler": 0}]) def test_rand_circ_cmap_routing( coupling_map, optimization_level, ai, qiskit_transpile_options @@ -108,7 +108,7 @@ def test_qv_circ_several_circuits_routing(): cloud_transpiler_service = TranspilerService( backend_name="ibm_brisbane", - ai=True, + ai='true', optimization_level=1, ) transpiled_circuit = cloud_transpiler_service.run([qv_circ] * 2) @@ -129,7 +129,7 @@ def test_qv_circ_wrong_input_routing(): cloud_transpiler_service = TranspilerService( backend_name="ibm_brisbane", - ai=True, + ai='true', optimization_level=1, ) @@ -138,7 +138,7 @@ def test_qv_circ_wrong_input_routing(): cloud_transpiler_service.run(circ_dict) -@pytest.mark.parametrize("ai", [False, True], ids=["no_ai", "ai"]) +@pytest.mark.parametrize("ai", ['false', 'true'], ids=["no_ai", "ai"]) def test_transpile_layout_reconstruction(ai): n_qubits = 27 From 7a55a2aaf210ad6f5a0fe87c046423dfbfe2035a Mon Sep 17 00:00:00 2001 From: chrisamirani Date: Wed, 26 Jun 2024 16:23:28 -0700 Subject: [PATCH 3/5] update demo --- ai-transpiler-demo.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ai-transpiler-demo.ipynb b/ai-transpiler-demo.ipynb index d7cce3d..4c18d50 100644 --- a/ai-transpiler-demo.ipynb +++ b/ai-transpiler-demo.ipynb @@ -212,7 +212,7 @@ "\n", "qiskit_lvl3_transpiler_service = TranspilerService(\n", " backend_name=\"ibm_torino\",\n", - " ai=False,\n", + " ai='false',\n", " optimization_level=3,\n", ")" ] @@ -282,7 +282,7 @@ "\n", "qiskit_lvl3_ai_transpiler_service = TranspilerService(\n", " backend_name=\"ibm_torino\",\n", - " ai=True,\n", + " ai='true',\n", " optimization_level=3,\n", ")" ] From 42a2ffc00ead574f94a717541936808ee95f0e22 Mon Sep 17 00:00:00 2001 From: chrisamirani Date: Wed, 26 Jun 2024 16:25:19 -0700 Subject: [PATCH 4/5] update docs --- README.md | 60 ++++++++++++++++++------------------ documentation-examples.ipynb | 4 +-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 0b2b11c..eda447f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pip install qiskit-transpiler-service By default, the package tries to authenticate to IBM Quantum services with the defined Qiskit API token, and uses your token from the `QISKIT_IBM_TOKEN` environment variable or from the file `~/.qiskit/qiskit-ibm.json` (under the section `default-ibm-quantum`). -*Note*: This library requires Qiskit 1.0 by default. +_Note_: This library requires Qiskit 1.0 by default. ## How to use the library @@ -24,37 +24,37 @@ The following examples demonstrate how to transpile circuits using the Qiskit tr 1. Create a circuit and call the Qiskit transpiler service to transpile the circuit with `ibm_sherbrooke` as the `backend_name`, 3 as the `optimization_level`, and not using AI during the transpilation. - ```python - from qiskit.circuit.library import EfficientSU2 - from qiskit_transpiler_service.transpiler_service import TranspilerService + ```python + from qiskit.circuit.library import EfficientSU2 + from qiskit_transpiler_service.transpiler_service import TranspilerService - circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() + circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() - cloud_transpiler_service = TranspilerService( - backend_name="ibm_sherbrooke", - ai=False, - optimization_level=3, - ) - transpiled_circuit = cloud_transpiler_service.run(circuit) - ``` + cloud_transpiler_service = TranspilerService( + backend_name="ibm_sherbrooke", + ai='false', + optimization_level=3, + ) + transpiled_circuit = cloud_transpiler_service.run(circuit) + ``` -*Note:* you only can use `backend_name` devices you are allowed to with your IBM Quantum Account. Apart from the `backend_name`, the `TranspilerService` also allows `coupling_map` as parameter. +_Note:_ you only can use `backend_name` devices you are allowed to with your IBM Quantum Account. Apart from the `backend_name`, the `TranspilerService` also allows `coupling_map` as parameter. 2. Produce a similar circuit and transpile it, requesting AI transpiling capabilities by setting the flag `ai` to `True`: - ```python - from qiskit.circuit.library import EfficientSU2 - from qiskit_transpiler_service.transpiler_service import TranspilerService + ```python + from qiskit.circuit.library import EfficientSU2 + from qiskit_transpiler_service.transpiler_service import TranspilerService - circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() + circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() - cloud_transpiler_service = TranspilerService( - backend_name="ibm_sherbrooke", - ai=True, - optimization_level=1, - ) - transpiled_circuit = cloud_transpiler_service.run(circuit) - ``` + cloud_transpiler_service = TranspilerService( + backend_name="ibm_sherbrooke", + ai='true', + optimization_level=1, + ) + transpiled_circuit = cloud_transpiler_service.run(circuit) + ``` ### Using the AIRouting pass manually @@ -108,9 +108,9 @@ The synthesis respects the coupling map of the device: it can be run safely afte The following synthesis passes are available from `qiskit_transpiler_service.ai.synthesis`: -- *AICliffordSynthesis*: Synthesis for [Clifford](https://docs.quantum.ibm.com/api/qiskit/qiskit.quantum_info.Clifford) circuits (blocks of `H`, `S` and `CX` gates). Currently up to 9 qubit blocks. -- *AILinearFunctionSynthesis*: Synthesis for [Linear Function](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.LinearFunction) circuits (blocks of `CX` and `SWAP` gates). Currently up to 9 qubit blocks. -- *AIPermutationSynthesis*: Synthesis for [Permutation](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.Permutation#permutation) circuits (blocks of `SWAP` gates). Currently available for 65, 33, and 27 qubit blocks. +- _AICliffordSynthesis_: Synthesis for [Clifford](https://docs.quantum.ibm.com/api/qiskit/qiskit.quantum_info.Clifford) circuits (blocks of `H`, `S` and `CX` gates). Currently up to 9 qubit blocks. +- _AILinearFunctionSynthesis_: Synthesis for [Linear Function](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.LinearFunction) circuits (blocks of `CX` and `SWAP` gates). Currently up to 9 qubit blocks. +- _AIPermutationSynthesis_: Synthesis for [Permutation](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.Permutation#permutation) circuits (blocks of `SWAP` gates). Currently available for 65, 33, and 27 qubit blocks. We expect to gradually increase the size of the supported blocks. @@ -126,9 +126,9 @@ For sub-circuit to be synthesized by the AI synthesis passes, it must lay on a c To complement the synthesis passes we also provide custom collection passes for Cliffords, Linear Functions and Permutations that can be imported from `qiskit_transpiler_service.ai.collection`: -- *CollectCliffords*: Collects `Clifford` blocks as `Instruction` objects and stores the original sub-circuit to compare against it after synthesis. -- *CollectLinearFunctions*: Collects blocks of `SWAP` and `CX` as `LinearFunction` objects and stores the original sub-circuit to compare against it after synthesis. -- *CollectPermutations*: Collects blocks of `SWAP` circuits as `Permutations`. +- _CollectCliffords_: Collects `Clifford` blocks as `Instruction` objects and stores the original sub-circuit to compare against it after synthesis. +- _CollectLinearFunctions_: Collects blocks of `SWAP` and `CX` as `LinearFunction` objects and stores the original sub-circuit to compare against it after synthesis. +- _CollectPermutations_: Collects blocks of `SWAP` circuits as `Permutations`. These custom collection passes limit the sizes of the collected sub-circuits so that they are supported by the AI synthesis passes, so it is recommended to use them after the routing passes and before the synthesis passes to get a better optimization overall. diff --git a/documentation-examples.ipynb b/documentation-examples.ipynb index 76e8c5d..494179d 100644 --- a/documentation-examples.ipynb +++ b/documentation-examples.ipynb @@ -22,7 +22,7 @@ "\n", "cloud_transpiler_service = TranspilerService(\n", " backend_name=\"ibm_sherbrooke\",\n", - " ai=False,\n", + " ai='false',\n", " optimization_level=3,\n", ")\n", "transpiled_circuit_no_ai = cloud_transpiler_service.run(circuit)" @@ -50,7 +50,7 @@ "\n", "cloud_transpiler_service = TranspilerService(\n", " backend_name=\"ibm_sherbrooke\",\n", - " ai=True,\n", + " ai='true',\n", " optimization_level=1,\n", ")\n", "transpiled_circuit_ai = cloud_transpiler_service.run(circuit)" From bdf0dd3ebe8d35e8c8d37ed620954d48dd6cdf7f Mon Sep 17 00:00:00 2001 From: chrisamirani Date: Wed, 26 Jun 2024 16:32:34 -0700 Subject: [PATCH 5/5] update docs --- README.md | 62 ++++++++++++++++++------------------ documentation-examples.ipynb | 4 +-- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 0b2b11c..b5c6da9 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pip install qiskit-transpiler-service By default, the package tries to authenticate to IBM Quantum services with the defined Qiskit API token, and uses your token from the `QISKIT_IBM_TOKEN` environment variable or from the file `~/.qiskit/qiskit-ibm.json` (under the section `default-ibm-quantum`). -*Note*: This library requires Qiskit 1.0 by default. +_Note_: This library requires Qiskit 1.0 by default. ## How to use the library @@ -24,37 +24,37 @@ The following examples demonstrate how to transpile circuits using the Qiskit tr 1. Create a circuit and call the Qiskit transpiler service to transpile the circuit with `ibm_sherbrooke` as the `backend_name`, 3 as the `optimization_level`, and not using AI during the transpilation. - ```python - from qiskit.circuit.library import EfficientSU2 - from qiskit_transpiler_service.transpiler_service import TranspilerService + ```python + from qiskit.circuit.library import EfficientSU2 + from qiskit_transpiler_service.transpiler_service import TranspilerService - circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() + circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() - cloud_transpiler_service = TranspilerService( - backend_name="ibm_sherbrooke", - ai=False, - optimization_level=3, - ) - transpiled_circuit = cloud_transpiler_service.run(circuit) - ``` + cloud_transpiler_service = TranspilerService( + backend_name="ibm_sherbrooke", + ai='false', + optimization_level=3, + ) + transpiled_circuit = cloud_transpiler_service.run(circuit) + ``` -*Note:* you only can use `backend_name` devices you are allowed to with your IBM Quantum Account. Apart from the `backend_name`, the `TranspilerService` also allows `coupling_map` as parameter. +_Note:_ you only can use `backend_name` devices you are allowed to with your IBM Quantum Account. Apart from the `backend_name`, the `TranspilerService` also allows `coupling_map` as parameter. -2. Produce a similar circuit and transpile it, requesting AI transpiling capabilities by setting the flag `ai` to `True`: +2. Produce a similar circuit and transpile it, requesting AI transpiling capabilities by setting the flag `ai` to `'true'`: - ```python - from qiskit.circuit.library import EfficientSU2 - from qiskit_transpiler_service.transpiler_service import TranspilerService + ```python + from qiskit.circuit.library import EfficientSU2 + from qiskit_transpiler_service.transpiler_service import TranspilerService - circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() + circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose() - cloud_transpiler_service = TranspilerService( - backend_name="ibm_sherbrooke", - ai=True, - optimization_level=1, - ) - transpiled_circuit = cloud_transpiler_service.run(circuit) - ``` + cloud_transpiler_service = TranspilerService( + backend_name="ibm_sherbrooke", + ai='true', + optimization_level=1, + ) + transpiled_circuit = cloud_transpiler_service.run(circuit) + ``` ### Using the AIRouting pass manually @@ -108,9 +108,9 @@ The synthesis respects the coupling map of the device: it can be run safely afte The following synthesis passes are available from `qiskit_transpiler_service.ai.synthesis`: -- *AICliffordSynthesis*: Synthesis for [Clifford](https://docs.quantum.ibm.com/api/qiskit/qiskit.quantum_info.Clifford) circuits (blocks of `H`, `S` and `CX` gates). Currently up to 9 qubit blocks. -- *AILinearFunctionSynthesis*: Synthesis for [Linear Function](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.LinearFunction) circuits (blocks of `CX` and `SWAP` gates). Currently up to 9 qubit blocks. -- *AIPermutationSynthesis*: Synthesis for [Permutation](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.Permutation#permutation) circuits (blocks of `SWAP` gates). Currently available for 65, 33, and 27 qubit blocks. +- _AICliffordSynthesis_: Synthesis for [Clifford](https://docs.quantum.ibm.com/api/qiskit/qiskit.quantum_info.Clifford) circuits (blocks of `H`, `S` and `CX` gates). Currently up to 9 qubit blocks. +- _AILinearFunctionSynthesis_: Synthesis for [Linear Function](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.LinearFunction) circuits (blocks of `CX` and `SWAP` gates). Currently up to 9 qubit blocks. +- _AIPermutationSynthesis_: Synthesis for [Permutation](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.Permutation#permutation) circuits (blocks of `SWAP` gates). Currently available for 65, 33, and 27 qubit blocks. We expect to gradually increase the size of the supported blocks. @@ -126,9 +126,9 @@ For sub-circuit to be synthesized by the AI synthesis passes, it must lay on a c To complement the synthesis passes we also provide custom collection passes for Cliffords, Linear Functions and Permutations that can be imported from `qiskit_transpiler_service.ai.collection`: -- *CollectCliffords*: Collects `Clifford` blocks as `Instruction` objects and stores the original sub-circuit to compare against it after synthesis. -- *CollectLinearFunctions*: Collects blocks of `SWAP` and `CX` as `LinearFunction` objects and stores the original sub-circuit to compare against it after synthesis. -- *CollectPermutations*: Collects blocks of `SWAP` circuits as `Permutations`. +- _CollectCliffords_: Collects `Clifford` blocks as `Instruction` objects and stores the original sub-circuit to compare against it after synthesis. +- _CollectLinearFunctions_: Collects blocks of `SWAP` and `CX` as `LinearFunction` objects and stores the original sub-circuit to compare against it after synthesis. +- _CollectPermutations_: Collects blocks of `SWAP` circuits as `Permutations`. These custom collection passes limit the sizes of the collected sub-circuits so that they are supported by the AI synthesis passes, so it is recommended to use them after the routing passes and before the synthesis passes to get a better optimization overall. diff --git a/documentation-examples.ipynb b/documentation-examples.ipynb index 76e8c5d..494179d 100644 --- a/documentation-examples.ipynb +++ b/documentation-examples.ipynb @@ -22,7 +22,7 @@ "\n", "cloud_transpiler_service = TranspilerService(\n", " backend_name=\"ibm_sherbrooke\",\n", - " ai=False,\n", + " ai='false',\n", " optimization_level=3,\n", ")\n", "transpiled_circuit_no_ai = cloud_transpiler_service.run(circuit)" @@ -50,7 +50,7 @@ "\n", "cloud_transpiler_service = TranspilerService(\n", " backend_name=\"ibm_sherbrooke\",\n", - " ai=True,\n", + " ai='true',\n", " optimization_level=1,\n", ")\n", "transpiled_circuit_ai = cloud_transpiler_service.run(circuit)"