# qiskit_ibm_transpiler
A library to use [Qiskit Transpiler Service](https://docs.quantum.ibm.com/guides/qiskit-transpiler-service) and the [AI transpiler passes](https://docs.quantum.ibm.com/transpile/ai-transpiler-passes).
**Note** The Qiskit Transpiler Service and the AI transpiler passes use different experimental services that are only available for IBM Quantum Premium Plan users. This library and the releated services are an alpha release, subject to change.
## Installing the qiskit-ibm-transpiler
To use the Qiskit IBM Transpiler, install the `qiskit-ibm-transpiler` package:
```sh
pip install qiskit-ibm-transpiler
```
to use it with the ability to run the available AI-powered transpiler passes (except `AIPauliNetworkSynthesis`) in local mode, install it as:
```sh
pip install qiskit-ibm-traspiler[ai-local-mode]
```
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 or greater.
## How to use the library
### Using local mode
### Using the Qiskit IBM Transpiler
The following examples demonstrate how to transpile circuits using the Qiskit IBM Transpiler with different parameters.
1. Create a circuit and call the Qiskit IBM Transpiler 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_ibm_transpiler.transpiler_service import TranspilerService
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)
```
_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_ibm_transpiler.transpiler_service import TranspilerService
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)
```
### Using the AIRouting pass manually
The `AIRouting` pass acts both as a layout stage and a routing stage. It can be used within a `PassManager` as follows:
```python
from qiskit.transpiler import PassManager
from qiskit_ibm_transpiler.ai.routing import AIRouting
from qiskit.circuit.library import EfficientSU2
ai_passmanager = PassManager([
AIRouting(backend_name="ibm_sherbrooke", optimization_level=2, layout_mode="optimize")
])
circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose()
transpiled_circuit = ai_passmanager.run(circuit)
```
Here, the `backend_name` determines which backend to route for, the `optimization_level` (1, 2, or 3) determines the computational effort to spend in the process (higher usually gives better results but takes longer), and the `layout_mode` specifies how to handle the layout selection.
The `layout_mode` includes the following options:
- `keep`: This respects the layout set by the previous transpiler passes (or uses the trivial layout if not set). It is typically only used when the circuit must be run on specific qubits of the device. It often produces worse results because it has less room for optimization.
- `improve`: This uses the layout set by the previous transpiler passes as a starting point. It is useful when you have a good initial guess for the layout; for example, for circuits that are built in a way that approximately follows the device's coupling map. It is also useful if you want to try other specific layout passes combined with the `AIRouting` pass.
- `optimize`: This is the default mode. It works best for general circuits where you might not have good layout guesses. This mode ignores previous layout selections.
### Using the AI circuit synthesis passes
The AI circuit synthesis passes allow you to optimize pieces of different circuit types ([Clifford](/api/qiskit/qiskit.quantum_info.Clifford), [Linear Function](/api/qiskit/qiskit.circuit.library.LinearFunction), [Permutation](/api/qiskit/qiskit.circuit.library.Permutation#permutation), [Pauli Network](/api/qiskit/qiskit.circuit.library.PauliNetwork)) by re-synthesizing them. A typical way to use the synthesis pass is as follows:
```python
from qiskit.transpiler import PassManager
from qiskit_ibm_transpiler.ai.routing import AIRouting
from qiskit_ibm_transpiler.ai.synthesis import AILinearFunctionSynthesis
from qiskit_ibm_transpiler.ai.collection import CollectLinearFunctions
from qiskit_ibm_transpiler.ai.synthesis import AIPauliNetworkSynthesis
from qiskit_ibm_transpiler.ai.collection import CollectPauliNetworks
from qiskit.circuit.library import EfficientSU2
ai_passmanager = PassManager([
AIRouting(backend_name="ibm_quebec", optimization_level=3, layout_mode="optimize"), # Route circuit
CollectLinearFunctions(), # Collect Linear Function blocks
AILinearFunctionSynthesis(backend_name="ibm_quebec") # Re-synthesize Linear Function blocks
CollectPauliNetworks(), # Collect Pauli Networks blocks
AIPauliNetworkSynthesis(backend_name="ibm_cairo"), # Re-synthesize Pauli Network blocks
])
circuit = EfficientSU2(10, entanglement="full", reps=1).decompose()
transpiled_circuit = ai_passmanager.run(circuit)
```
The synthesis respects the coupling map of the device: it can be run safely after other routing passes without "messing up" the circuit, so the overall circuit will still follow the device restrictions. By default, the synthesis will replace the original sub-circuit only if the synthesized sub-circuit improves the original (currently only checking `CNOT` count), but this can be forced to always replace the circuit by setting `replace_only_if_better=False`.
The following synthesis passes are available from `qiskit_ibm_transpiler.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.
- _AIPauliNetworkSynthesis_: Synthesis for [Pauli Network](/api/qiskit/qiskit.circuit.library.PauliNetwork) circuits (blocks of `H`, `S`, `SX`, `CX`, `RX`, `RY` and `RZ` gates). Currently up to six qubit blocks.
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_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.
For sub-circuit to be synthesized by the AI synthesis passes, it must lay on a connected subgraph of the coupling map (this can be ensured by just doing a routing pass previous to collecting the blocks, but this is not the only way to do it). The synthesis passes will automatically check if a the specific subgraph where the sub-circuit lays is supported, and if it is not supported it will raise a warning and just leave the original sub-circuit as it is.
To complement the synthesis passes we also provide custom collection passes for Cliffords, Linear Functions and Permutations that can be imported from `qiskit_ibm_transpiler.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`.
- _CollectPauliNetworks_: Collects Pauli Network blocks and stores the original sub-circuit to compare against it after synthesis.
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.
### Customize logs
The library is prepared to let the user log the messages they want. For that, users only have to add the following code to their code:
```python
import logging
logging.getLogger("qiskit_ibm_transpiler").setLevel(logging.X)
```
where X can be: `NOTSET`, `DEBUG`, `INFO`, `WARNING`, `ERROR` or `CRITICAL`
## Citation
If you use any AI-powered feature from the Qiskit IBM Transpiler in your research, use the following recommended citation:
```
@misc{2405.13196,
Author = {David Kremer and Victor Villar and Hanhee Paik and Ivan Duran and Ismael Faro and Juan Cruz-Benito},
Title = {Practical and efficient quantum circuit synthesis and transpiling with Reinforcement Learning},
Year = {2024},
Eprint = {arXiv:2405.13196},
}
```
Raw data
{
"_id": null,
"home_page": "https://github.com/Qiskit/qiskit-ibm-transpiler",
"name": "qiskit-ibm-transpiler",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "qiskit, ai, transpiler, routing",
"author": "Qiskit Development Team",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/b5/ca/bb0cdfb89bf05cb8e9b29acab15ddda8e162824db9b39eeabc915049254b/qiskit_ibm_transpiler-0.9.1.tar.gz",
"platform": null,
"description": "# qiskit_ibm_transpiler\n\nA library to use [Qiskit Transpiler Service](https://docs.quantum.ibm.com/guides/qiskit-transpiler-service) and the [AI transpiler passes](https://docs.quantum.ibm.com/transpile/ai-transpiler-passes).\n\n**Note** The Qiskit Transpiler Service and the AI transpiler passes use different experimental services that are only available for IBM Quantum Premium Plan users. This library and the releated services are an alpha release, subject to change.\n\n## Installing the qiskit-ibm-transpiler\n\nTo use the Qiskit IBM Transpiler, install the `qiskit-ibm-transpiler` package:\n\n```sh\npip install qiskit-ibm-transpiler\n```\n\nto use it with the ability to run the available AI-powered transpiler passes (except `AIPauliNetworkSynthesis`) in local mode, install it as:\n\n```sh\npip install qiskit-ibm-traspiler[ai-local-mode]\n```\n\nBy 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`).\n\n_Note_: This library requires Qiskit 1.0 or greater.\n\n## How to use the library\n\n### Using local mode\n\n### Using the Qiskit IBM Transpiler\n\nThe following examples demonstrate how to transpile circuits using the Qiskit IBM Transpiler with different parameters.\n\n1. Create a circuit and call the Qiskit IBM Transpiler to transpile the circuit with `ibm_sherbrooke` as the `backend_name`, 3 as the `optimization_level`, and not using AI during the transpilation.\n\n ```python\n from qiskit.circuit.library import EfficientSU2\n from qiskit_ibm_transpiler.transpiler_service import TranspilerService\n\n circuit = EfficientSU2(101, entanglement=\"circular\", reps=1).decompose()\n\n cloud_transpiler_service = TranspilerService(\n backend_name=\"ibm_sherbrooke\",\n ai='false',\n optimization_level=3,\n )\n transpiled_circuit = cloud_transpiler_service.run(circuit)\n ```\n\n_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.\n\n2. Produce a similar circuit and transpile it, requesting AI transpiling capabilities by setting the flag `ai` to `'true'`:\n\n ```python\n from qiskit.circuit.library import EfficientSU2\n from qiskit_ibm_transpiler.transpiler_service import TranspilerService\n\n circuit = EfficientSU2(101, entanglement=\"circular\", reps=1).decompose()\n\n cloud_transpiler_service = TranspilerService(\n backend_name=\"ibm_sherbrooke\",\n ai='true',\n optimization_level=1,\n )\n transpiled_circuit = cloud_transpiler_service.run(circuit)\n ```\n\n### Using the AIRouting pass manually\n\nThe `AIRouting` pass acts both as a layout stage and a routing stage. It can be used within a `PassManager` as follows:\n\n```python\nfrom qiskit.transpiler import PassManager\nfrom qiskit_ibm_transpiler.ai.routing import AIRouting\nfrom qiskit.circuit.library import EfficientSU2\n\nai_passmanager = PassManager([\n AIRouting(backend_name=\"ibm_sherbrooke\", optimization_level=2, layout_mode=\"optimize\")\n])\n\ncircuit = EfficientSU2(101, entanglement=\"circular\", reps=1).decompose()\n\ntranspiled_circuit = ai_passmanager.run(circuit)\n```\n\nHere, the `backend_name` determines which backend to route for, the `optimization_level` (1, 2, or 3) determines the computational effort to spend in the process (higher usually gives better results but takes longer), and the `layout_mode` specifies how to handle the layout selection.\nThe `layout_mode` includes the following options:\n\n- `keep`: This respects the layout set by the previous transpiler passes (or uses the trivial layout if not set). It is typically only used when the circuit must be run on specific qubits of the device. It often produces worse results because it has less room for optimization.\n- `improve`: This uses the layout set by the previous transpiler passes as a starting point. It is useful when you have a good initial guess for the layout; for example, for circuits that are built in a way that approximately follows the device's coupling map. It is also useful if you want to try other specific layout passes combined with the `AIRouting` pass.\n- `optimize`: This is the default mode. It works best for general circuits where you might not have good layout guesses. This mode ignores previous layout selections.\n\n### Using the AI circuit synthesis passes\n\nThe AI circuit synthesis passes allow you to optimize pieces of different circuit types ([Clifford](/api/qiskit/qiskit.quantum_info.Clifford), [Linear Function](/api/qiskit/qiskit.circuit.library.LinearFunction), [Permutation](/api/qiskit/qiskit.circuit.library.Permutation#permutation), [Pauli Network](/api/qiskit/qiskit.circuit.library.PauliNetwork)) by re-synthesizing them. A typical way to use the synthesis pass is as follows:\n\n```python\nfrom qiskit.transpiler import PassManager\n\nfrom qiskit_ibm_transpiler.ai.routing import AIRouting\nfrom qiskit_ibm_transpiler.ai.synthesis import AILinearFunctionSynthesis\nfrom qiskit_ibm_transpiler.ai.collection import CollectLinearFunctions\nfrom qiskit_ibm_transpiler.ai.synthesis import AIPauliNetworkSynthesis\nfrom qiskit_ibm_transpiler.ai.collection import CollectPauliNetworks\nfrom qiskit.circuit.library import EfficientSU2\n\nai_passmanager = PassManager([\n AIRouting(backend_name=\"ibm_quebec\", optimization_level=3, layout_mode=\"optimize\"), # Route circuit\n CollectLinearFunctions(), # Collect Linear Function blocks\n AILinearFunctionSynthesis(backend_name=\"ibm_quebec\") # Re-synthesize Linear Function blocks\n CollectPauliNetworks(), # Collect Pauli Networks blocks\n AIPauliNetworkSynthesis(backend_name=\"ibm_cairo\"), # Re-synthesize Pauli Network blocks\n])\n\ncircuit = EfficientSU2(10, entanglement=\"full\", reps=1).decompose()\n\ntranspiled_circuit = ai_passmanager.run(circuit)\n```\n\nThe synthesis respects the coupling map of the device: it can be run safely after other routing passes without \"messing up\" the circuit, so the overall circuit will still follow the device restrictions. By default, the synthesis will replace the original sub-circuit only if the synthesized sub-circuit improves the original (currently only checking `CNOT` count), but this can be forced to always replace the circuit by setting `replace_only_if_better=False`.\n\nThe following synthesis passes are available from `qiskit_ibm_transpiler.ai.synthesis`:\n\n- _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.\n- _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.\n- _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.\n- _AIPauliNetworkSynthesis_: Synthesis for [Pauli Network](/api/qiskit/qiskit.circuit.library.PauliNetwork) circuits (blocks of `H`, `S`, `SX`, `CX`, `RX`, `RY` and `RZ` gates). Currently up to six qubit blocks.\n\nWe expect to gradually increase the size of the supported blocks.\n\nAll 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.\n\n```python\nAILinearFunctionSynthesis(backend_name=\"ibm_quebec\", max_threads=20) # Re-synthesize Linear Function blocks using 20 threads max\n```\n\nYou 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.\n\nFor sub-circuit to be synthesized by the AI synthesis passes, it must lay on a connected subgraph of the coupling map (this can be ensured by just doing a routing pass previous to collecting the blocks, but this is not the only way to do it). The synthesis passes will automatically check if a the specific subgraph where the sub-circuit lays is supported, and if it is not supported it will raise a warning and just leave the original sub-circuit as it is.\n\nTo complement the synthesis passes we also provide custom collection passes for Cliffords, Linear Functions and Permutations that can be imported from `qiskit_ibm_transpiler.ai.collection`:\n\n- _CollectCliffords_: Collects `Clifford` blocks as `Instruction` objects and stores the original sub-circuit to compare against it after synthesis.\n- _CollectLinearFunctions_: Collects blocks of `SWAP` and `CX` as `LinearFunction` objects and stores the original sub-circuit to compare against it after synthesis.\n- _CollectPermutations_: Collects blocks of `SWAP` circuits as `Permutations`.\n- _CollectPauliNetworks_: Collects Pauli Network blocks and stores the original sub-circuit to compare against it after synthesis.\n\nThese 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.\n\n### Customize logs\n\nThe library is prepared to let the user log the messages they want. For that, users only have to add the following code to their code:\n\n```python\nimport logging\n\nlogging.getLogger(\"qiskit_ibm_transpiler\").setLevel(logging.X)\n```\n\nwhere X can be: `NOTSET`, `DEBUG`, `INFO`, `WARNING`, `ERROR` or `CRITICAL`\n\n## Citation\n\nIf you use any AI-powered feature from the Qiskit IBM Transpiler in your research, use the following recommended citation:\n\n```\n@misc{2405.13196,\nAuthor = {David Kremer and Victor Villar and Hanhee Paik and Ivan Duran and Ismael Faro and Juan Cruz-Benito},\nTitle = {Practical and efficient quantum circuit synthesis and transpiling with Reinforcement Learning},\nYear = {2024},\nEprint = {arXiv:2405.13196},\n}\n```\n",
"bugtrack_url": null,
"license": "Apache 2.0",
"summary": "A library to use Qiskit IBM Transpiler (https://docs.quantum.ibm.com/transpile/qiskit-ibm-transpiler) and the AI transpiler passes (https://docs.quantum.ibm.com/transpile/ai-transpiler-passes)",
"version": "0.9.1",
"project_urls": {
"Bug Tracker": "https://github.com/Qiskit/qiskit-ibm-transpiler/issues",
"Documentation": "https://github.com/Qiskit/qiskit-ibm-transpiler",
"Homepage": "https://github.com/Qiskit/qiskit-ibm-transpiler",
"Source Code": "https://github.com/Qiskit/qiskit-ibm-transpiler"
},
"split_keywords": [
"qiskit",
" ai",
" transpiler",
" routing"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "65a6d65732b6010369b933d028e361a95638469d6ace083e24bec4614459129c",
"md5": "0fffd41319c0d685dfd9eb9f0e28dacd",
"sha256": "2447229fe2aacbff1d4499f1b40816caf76e5c7db24a44c2d2b1718da3e914df"
},
"downloads": -1,
"filename": "qiskit_ibm_transpiler-0.9.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0fffd41319c0d685dfd9eb9f0e28dacd",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 45172,
"upload_time": "2024-11-15T19:00:17",
"upload_time_iso_8601": "2024-11-15T19:00:17.039357Z",
"url": "https://files.pythonhosted.org/packages/65/a6/d65732b6010369b933d028e361a95638469d6ace083e24bec4614459129c/qiskit_ibm_transpiler-0.9.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b5cabb0cdfb89bf05cb8e9b29acab15ddda8e162824db9b39eeabc915049254b",
"md5": "be5976e5fab8cec4d8e57451f4dab7aa",
"sha256": "f3473dd291828b8f93241fa3b12f131b61c49eb0c1b5ada69c945b58a67966c5"
},
"downloads": -1,
"filename": "qiskit_ibm_transpiler-0.9.1.tar.gz",
"has_sig": false,
"md5_digest": "be5976e5fab8cec4d8e57451f4dab7aa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 39571,
"upload_time": "2024-11-15T19:00:21",
"upload_time_iso_8601": "2024-11-15T19:00:21.198330Z",
"url": "https://files.pythonhosted.org/packages/b5/ca/bb0cdfb89bf05cb8e9b29acab15ddda8e162824db9b39eeabc915049254b/qiskit_ibm_transpiler-0.9.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-15 19:00:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Qiskit",
"github_project": "qiskit-ibm-transpiler",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "qiskit-ibm-transpiler"
}