Skip to content

Commit

Permalink
fix: Correctly parse string boolean for ai param (#7)
Browse files Browse the repository at this point in the history
* Correctly parse string boolean for ai param

* User literal values in argument for ai

* update demo

* update docs

* update docs
  • Loading branch information
nihaocami authored Jun 28, 2024
1 parent 976d9c3 commit 1935200
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 47 deletions.
62 changes: 31 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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.

Expand All @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions ai-transpiler-demo.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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",
")"
]
Expand Down Expand Up @@ -281,7 +281,7 @@
"source": [
"qiskit_lvl3_ai_transpiler_service = TranspilerService(\n",
" backend_name=\"ibm_torino\",\n",
" ai=True,\n",
" ai='true',\n",
" optimization_level=3,\n",
")"
]
Expand Down
4 changes: 2 additions & 2 deletions documentation-examples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand Down Expand Up @@ -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)"
Expand Down
8 changes: 4 additions & 4 deletions qiskit_transpiler_service/transpiler_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"""

import logging
from typing import Dict, List, Union
from typing import Dict, List, Union, Literal

from qiskit import QuantumCircuit

Expand All @@ -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.
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions qiskit_transpiler_service/wrappers/transpile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
):
Expand Down
12 changes: 6 additions & 6 deletions tests/test_transpiler_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}],
Expand All @@ -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}],
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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,
)

Expand All @@ -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

Expand Down

0 comments on commit 1935200

Please sign in to comment.