Skip to content

Commit

Permalink
Update documentation about Qiskit Transpiler Service & AI transpiler …
Browse files Browse the repository at this point in the history
…passes (#797)

Adding documentation of the new features and changes available after the
release of versions 0.2.0 & 0.2.1 of the `qiskit_transpiler_service`

---------

Co-authored-by: ABBY CROSS <[email protected]>
  • Loading branch information
cbjuan and abbycross authored Mar 4, 2024
1 parent 2d13c71 commit 62ad14b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 21 deletions.
64 changes: 55 additions & 9 deletions docs/transpile/ai-transpiler-passes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ The AI-powered transpiler passes are experimental passes that work as a drop-in
<Admonition type="note">
This is an experimental feature available only to the IBM Quantum Premium Plan.
The AI-powered transpiler passes are in alpha release status, subject to change.
If you have feedback or want to contact the developer team, please use this [Qiskit Slack Workspace channel](https://qiskit.slack.com/archives/C06KF8YHUAU).
</Admonition>

The following passes are currently available:

**Routing passes**
- `AIRouting`: Layout selection and circuit routing

The following passes will be available in Q1 2024.

**Circuit synthesis passes**
- `AICliffordSynthesis`: Clifford circuit synthesis
- `AILinearFunctionSynthesis`: Linear function circuit synthesis
Expand All @@ -37,21 +36,68 @@ from qiskit_transpiler_service.ai.routing import AIRouting
from qiskit.circuit.library import EfficientSU2

ai_passmanager = PassManager([
AIRouting(target="ibm_sherbrooke", optimization_level=2, layout_mode="optimize")
AIRouting(backend_name="ibm_sherbrooke", optimization_level=2, layout_mode="optimize")
])

circuit = EfficientSU2(120, entanglement="circular", reps=1).decompose()
circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose()

transpiled_circuit = ai_passmanager.run(circuit)
```

Here, the `target` determines which system 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.
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.

<Admonition type="tip" title="Recommendations">
- Learn [how to transpile circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) as part of Qiskit Patterns workflows using Qiskit Runtime.
- Review the [Qiskit transpiler service API documentation.](https://cloud-transpiler-experimental.quantum-computing.ibm.com/docs)
</Admonition>
## 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)) by re-synthesizing them. A typical way to use the synthesis pass is as follows:

```python
from qiskit.transpiler import PassManager

from qiskit_transpiler_service.ai.routing import AIRouting
from qiskit_transpiler_service.ai.synthesis import AILinearFunctionSynthesis
from qiskit_transpiler_service.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
CollectLinearFunctions(), # Collect Linear Function blocks
AILinearFunctionSynthesis(backend_name="ibm_cairo") # Re-synthesize Linear Function 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 disturbing 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_transpiler_service.ai.synthesis`:

- *AICliffordSynthesis*: Synthesis for [Clifford](/api/qiskit/qiskit.quantum_info.Clifford) circuits (blocks of `H`, `S`, and `CX` gates). Currently up to nine qubit blocks.
- *AILinearFunctionSynthesis*: Synthesis for [Linear Function](/api/qiskit/qiskit.circuit.library.LinearFunction) circuits (blocks of `CX` and `SWAP` gates). Currently up to nine qubit blocks.
- *AIPermutationSynthesis*: Synthesis for [Permutation](/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.

All passes use a thread pool to send several requests in parallel. By default, the number for max threads is the number of cores plus four (default values for the `ThreadPoolExecutor` Python object). However, you can set your own value with the `max_threads` argument at pass instantation. For example, the following line instantiates the `AILinearFunctionSynthesis` pass, which allows 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
```

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 the AI synthesis passes to synthesize a sub-circuit, it must lay on a connected subgraph of the coupling map (one way to do this is with a routing pass before collecting the blocks, but this is not the only way to do it). The synthesis passes will automatically check that the specific subgraph is supported, and if not, it will raise a warning and leave the original sub-circuit unchanged.

The following custom collection passes for Cliffords, Linear Functions and Permutations that can be imported from `qiskit_transpiler_service.ai.collection` also complement the synthesis passes:

- *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 for a better overall optimization.
28 changes: 16 additions & 12 deletions docs/transpile/qiskit-transpiler-service.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The Qiskit transpiler service offers a Python library to seamlessly integrate th
<Admonition type="note">
This experimental service is only available for IBM Quantum Premium Plan users.
The service is an alpha release, subject to change.
If you have feedback or want to contact the developer team, please use this [Qiskit Slack Workspace channel](https://qiskit.slack.com/archives/C06KF8YHUAU).
</Admonition>

<span id="install-transpiler-service"></span>
Expand All @@ -25,9 +26,11 @@ 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 package requires Qiskit 1.0 by default.

## qiskit-transpiler-service transpile options

- `target` (optional, str) - A system name as it would be expected by QiskitRuntimeService (for example, `ibm_sherbrooke`). If this is set, the transpile method uses the layout from the specified system for the transpilation operation. If any other option is set that impacts these settings, such as `coupling_map`, the `target` settings are overridden.
- `backend_name` (optional, str) - A backend name as it would be expected by QiskitRuntimeService (for example, `ibm_sherbrooke`). If this is set, the transpile method uses the layout from the specified backend for the transpilation operation. If any other option is set that impacts these settings, such as `coupling_map`, the `backend_name` settings are overridden.
- `coupling_map` (optional, List[List[int]]) - A valid coupling map list (for example, [[0,1],[1,2]]). If this is set, the transpile method uses this coupling map for the transpilation operation. If defined, it overrides any value specified for `target`.
- `optimization_level` (int) - The potential optimization level to apply during the transpilation process. Valid values are [1,2,3], where 1 is the least optimization (and fastest), and 3 the most optimization (and most time-intensive).
- `ai` (bool) - Whether to use AI capabilities during transpilation. The AI capabilities available can be for `AIRouting` transpiling passes or other AI synthesis methods. If this value is `True`, the service applies different AI-powered transpiling passes depending on the `optimization_level` requested.
Expand All @@ -38,36 +41,37 @@ By default, the package tries to authenticate to IBM Quantum services with the d

The following examples demonstrate how to transpile circuits using the Qiskit transpiler service with different parameters.

1. Create a random circuit and call the Qiskit transpiler service to transpile the circuit with `ibm_cairo` as the `target`, 1 as the `optimization_level`, and not using AI during the transpilation.
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 without using AI during the transpilation.

```python
from qiskit.circuit.random import random_circuit
from qiskit.circuit.library import EfficientSU2
from qiskit_transpiler_service.transpiler_service import TranspilerService

random_circ = random_circuit(5, depth=3, seed=42).decompose(reps=3)
circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose()

cloud_transpiler_service = TranspilerService(
target="ibm_cairo",
backend_name="ibm_sherbrooke",
ai=False,
optimization_level=1,
optimization_level=3,
)
transpiled_circuit = cloud_transpiler_service.run(random_circ)
transpiled_circuit = cloud_transpiler_service.run(circuit)
```
*Note*: you only can use backend_name devices you have access to with your IBM Quantum account. Apart from the `backend_name`, the `TranspilerService` also allows `coupling_map` as parameter.

1. Produce a similar random 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.random import random_circuit
from qiskit.circuit.library import EfficientSU2
from qiskit_transpiler_service.transpiler_service import TranspilerService

random_circ = random_circuit(5, depth=3, seed=42).decompose(reps=3)
circuit = EfficientSU2(101, entanglement="circular", reps=1).decompose()

cloud_transpiler_service = TranspilerService(
target="ibm_cairo",
backend_name="ibm_sherbrooke",
ai=True,
optimization_level=1,
)
transpiled_circuit = cloud_transpiler_service.run(random_circ)
transpiled_circuit = cloud_transpiler_service.run(circuit)
```

## Next steps
Expand Down

0 comments on commit 62ad14b

Please sign in to comment.