Remove stale translations (#1040)
I was keeping these around to debug https://github.com/Qiskit/documentation/issues/705, but the files are resulting in issues because the docs are out of date. For example, they're blocking us from removing unused images. We can debug https://github.com/Qiskit/documentation/issues/705 by reverting this commit when iterating locally.
This commit is contained in:
parent
e75699974a
commit
dedfc4159c
|
@ -0,0 +1 @@
|
||||||
|
Empty file so Git preserves this folder.
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Migration guides",
|
|
||||||
"collapsed": true,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Introduction",
|
|
||||||
"url": "/api/migration-guides"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Migrate to Qiskit Runtime",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "How to migrate",
|
|
||||||
"url": "/api/migration-guides/qiskit-runtime"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Examples",
|
|
||||||
"url": "/api/migration-guides/qiskit-runtime-examples"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "qiskit_ibm_provider to qiskit_ibm_runtime",
|
|
||||||
"url": "/api/migration-guides/qiskit-runtime-from-provider"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Qiskit 0.44 changes",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "QuantumInstance deprecation",
|
|
||||||
"url": "/api/migration-guides/qiskit-quantum-instance"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "qiskit.algorithms new interface",
|
|
||||||
"url": "/api/migration-guides/qiskit-algorithms-module"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "qiskit.opflow deprecation",
|
|
||||||
"url": "/api/migration-guides/qiskit-opflow-module"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduction
|
|
||||||
description: Migrate to using the newest from Qiskit and Qiskit Runtime
|
|
||||||
---
|
|
||||||
|
|
||||||
# Introduction
|
|
||||||
|
|
||||||
We've prepared various migration guides to help you more effectively use Qiskit and Qiskit Runtime:
|
|
||||||
|
|
||||||
- Migrate to Qiskit Runtime
|
|
||||||
- [How to migrate](./qiskit-runtime)
|
|
||||||
- [Examples](./qiskit-runtime-examples)
|
|
||||||
- [Migrate `backend.run()` from `qiskit_ibm_provider` to `qiskit_ibm_runtime`](./qiskit-runtime-from-provider)
|
|
||||||
- Qiskit 0.44 changes
|
|
||||||
- [`qiskit.algorithms` new interface](./qiskit-algorithms-module)
|
|
||||||
- [`qiskit.opflow` deprecation](./qiskit-opflow-module)
|
|
||||||
- [`QuantumIntance` deprecation](./qiskit-quantum-instance)
|
|
|
@ -1,684 +0,0 @@
|
||||||
---
|
|
||||||
title: Qiskit 1.0 installation and packaging changes
|
|
||||||
description: Adapt to changes in installing and depending on Qiskit 1.0
|
|
||||||
---
|
|
||||||
|
|
||||||
# Qiskit 1.0 packaging changes
|
|
||||||
|
|
||||||
Qiskit 1.0 uses a different packaging structure than previous Qiskit versions and might cause problems in environments that use packages that are not ready for Qiskit 1.0.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
Do not try to upgrade an existing Python virtual environment to Qiskit 1.0 in-place.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
This guide is divided into the following sections. You only need to review the sections that are relevant to you.
|
|
||||||
|
|
||||||
- Users should read the [For users](#for-users) section.
|
|
||||||
- If you develop or maintain a package that depends on Qiskit, read the [For developers](#for-developers) section.
|
|
||||||
- If you are interested, review the [What is changing and why it changed](#why-did-this-happen) section.
|
|
||||||
- If you encounter problems installing or importing Qiskit 1.0, review the [Troubleshooting](#troubleshooting) section.
|
|
||||||
|
|
||||||
<span id="for-users"></span>
|
|
||||||
## For users
|
|
||||||
|
|
||||||
You must start a new virtual environment to install Qiskit 1.0.
|
|
||||||
It is very tricky and error-prone to upgrade an existing installation in-place to Qiskit 1.0.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The examples in this section use the `venv` module that is part of the Python standard library.
|
|
||||||
If you use a different tool, such as `virtualenv` or `conda`, consult its documentation for help.
|
|
||||||
|
|
||||||
For Linux and macOS commands, a bash-like syntax is used.
|
|
||||||
PowerShell is used for Windows commands.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="creating-a-venv"></span>
|
|
||||||
### Create the new environment
|
|
||||||
|
|
||||||
1. Create a new virtual environment, using your preferred version of Python 3.8 or later. Use any path you choose in place of `/path/to/qiskit-1.0-venv`.
|
|
||||||
|
|
||||||
````
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```bash
|
|
||||||
python3 -m venv /path/to/qiskit-1.0-venv
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```bash
|
|
||||||
python3 -m venv /path/to/qiskit-1.0-venv
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```powershell
|
|
||||||
python3 -m venv C:\path\to\qiskit-1.0-venv
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
````
|
|
||||||
|
|
||||||
<span id="activate"></span>
|
|
||||||
2. Activate the environment.
|
|
||||||
|
|
||||||
````
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```bash
|
|
||||||
source /path/to/qiskit-1.0-venv/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```bash
|
|
||||||
source /path/to/qiskit-1.0-venv/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```powershell
|
|
||||||
C:\path\to\qiskit-1.0-venv\Scripts\activate.ps1
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
````
|
|
||||||
|
|
||||||
3. Install packages as desired.
|
|
||||||
You should do this by using only one `pip install` command with all the dependencies on it.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install 'qiskit>=1'
|
|
||||||
```
|
|
||||||
|
|
||||||
You can optionally include additional packages by including them as arguments. For example:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install 'qiskit>=1' jupyterlab pandas matplotlib
|
|
||||||
```
|
|
||||||
|
|
||||||
Qiskit 1.0 includes breaking changes, so several packages are marked as not-yet-compatible with it. Therefore, you might see errors from `pip` until new versions of those packages are released. Old versions of packages might also depend on the legacy `qiskit-terra` package. Such packages might not return errors when running this command, but might raise an error when running `import qiskit`. You should not install any packages that depend directly on `qiskit-terra`.
|
|
||||||
|
|
||||||
<Admonition type="tip">
|
|
||||||
One way to require `pip` to forbid `qiskit-terra` from individual `install` commands is to use [a constraints file](https://pip.pypa.io/en/stable/user_guide/#constraints-files) that requires that `qiskit-terra` is set to an impossible version.
|
|
||||||
For example, a constraints file that includes the line `qiskit-terra>=1.0` will mean that if a dependency attempts to install `qiskit-terra`, no published versions will match the requirements.
|
|
||||||
|
|
||||||
We have provided such a file in a GitHub Gist at <https://qisk.it/1-0-constraints>, which you can use like this:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -c https://qisk.it/1-0-constraints qiskit [other packages]
|
|
||||||
```
|
|
||||||
|
|
||||||
If a package requires `qiskit-terra`, you will see [a resolution failure](#pip-resolution-impossible).
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
Do not install packages that are incompatible with Qiskit 1.0 on this virtual environment. If you need to use such packages, install them in a separate virtual environment with Qiskit 0.45 or 0.46.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
If you have an existing environment, you can use [`pipdeptree`](https://github.com/tox-dev/pipdeptree/blob/main/README.md#pipdeptree) to query the requirements of your installed packages to see if they require `qiskit<1`. For any that require `qiskit<1`, check for updates that make it compatible with Qiskit 1.0.
|
|
||||||
|
|
||||||
If you encounter issues, consult the [troubleshooting](#troubleshooting) section, or ask on [Qiskit Slack](https://qisk.it/join-slack). If you think there is a bug, you can [create an issue against Qiskit](https://github.com/Qiskit/qiskit/issues/new/choose).
|
|
||||||
|
|
||||||
4. If you are not planning to use the environment immediately, use the `deactivate` command to leave it.
|
|
||||||
|
|
||||||
<span id="activating-a-venv"></span>
|
|
||||||
### Use the new environment
|
|
||||||
|
|
||||||
Each time you start a new command line session, you must "activate" the environment by running the `activate` command:
|
|
||||||
|
|
||||||
````
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```bash
|
|
||||||
source /path/to/qiskit-1.0-venv/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```bash
|
|
||||||
source /path/to/qiskit-1.0-venv/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```powershell
|
|
||||||
C:\path\to\qiskit-1.0-venv\Scripts\activate.ps1
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
````
|
|
||||||
|
|
||||||
<span id="for-developers"></span>
|
|
||||||
## For developers
|
|
||||||
|
|
||||||
If you maintain a package that depends on Qiskit, use this information to learn how to correctly express your compatibility and test against Qiskit 1.0.
|
|
||||||
|
|
||||||
### Recommendations for requirements
|
|
||||||
|
|
||||||
We recommend that your package requires `qiskit>=0.45,<1` (or other appropriate lower bound) if you are not certain whether the package is compatible with Qiskit 1.0.
|
|
||||||
This is [the same recommendation being made for NumPy 2.0 compatibility.](https://github.com/numpy/numpy/issues/24300)
|
|
||||||
|
|
||||||
A Qiskit 1.0 release candidate, version 1.0.0rc1, will be released on 1 February 2024.
|
|
||||||
You should test your package against this, and as soon as possible, release a new (compatible) version of your package with its upper requirement unpinned.
|
|
||||||
|
|
||||||
### Recommendations for testing against Qiskit 1.0
|
|
||||||
|
|
||||||
These recommendations apply to testing proactively against the Qiskit `main` branch, and to testing against the 1.0.0rc1 (and later, if applicable) release candidate.
|
|
||||||
|
|
||||||
We do not recommend initially branch-protecting on CI success against the Qiskit `main` branch because Qiskit changes could prevent you from merging PRs.
|
|
||||||
After the release of Qiskit release candidates, and after all of your package's dependencies support Qiskit 1.0, we _do_ recommend branch-protecting on success against the latest release candidate, to ensure that the package remains compatible with Qiskit 1.0.
|
|
||||||
|
|
||||||
If neither your package, nor any of its transitive dependencies, has a requirement pin on `qiskit<1`, you should create a testing virtual environment as you normally would, in a single `pip install` command, and directly specify `qiskit==1.0.0rc1` or `qiskit==git+https://github.com/Qiskit/qiskit.git@main` as appropriate.
|
|
||||||
This is the most reliable way to ensure that you have a completely valid environment.
|
|
||||||
|
|
||||||
If the only component of your package's dependency graph that has a requirement pin on `qiskit<1` is your own package, you might want to have your CI suite first temporarily patch your requirements file to allow Qiskit 1.0, and then install the environment in a single step as before.
|
|
||||||
Alternatively, use the following rules for general-purpose environment upgrades, but switch to single-environment resolution as soon as feasible.
|
|
||||||
|
|
||||||
If at least one of your transitive dependencies does not yet have a release version that allows Qiskit 1.0 support, you must make manual changes.
|
|
||||||
There are several strategies to try, in approximate order of preference (most preferable to least):
|
|
||||||
|
|
||||||
- Install the problematic dependency from its own `main` branch, if its development version has relaxed the pin, so you can build the test environment in a single step.
|
|
||||||
- Exclude the use of that dependency from the test environment, if possible.
|
|
||||||
- Create a test environment in the same way you would normally, and then manually override it to use Qiskit 1.0.
|
|
||||||
|
|
||||||
#### Manually upgrade an existing environment
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
This process deliberately creates an invalid environment. Therefore, any test using it is less valid. Tests might appear to pass, but this does not guarantee that the package is compatible with Qiskit 1.0. This could happen because the environment is not self-consistent and could contain files that do not exist in a valid environment, or the behavior of an overridden package might change with Qiskit 1.0.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If one of your dependencies pins `qiskit<1` even on their development branch, it might not work in any way with Qiskit 1.0, and if your tests cannot run because of this, you might have to wait for them (or work with them) to become compatible.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
To upgrade an environment in situ, follow these steps:
|
|
||||||
|
|
||||||
1. Create an environment as usual, ensuring that there are no packages that extend the `qiskit` or `qiskit.providers` namespace installed.
|
|
||||||
|
|
||||||
2. Uninstall both `qiskit` and `qiskit-terra` to make sure that neither is present:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip uninstall --yes qiskit qiskit-terra
|
|
||||||
```
|
|
||||||
|
|
||||||
At this point, the environment's `site-packages` should not contain a `qiskit` directory. You don't need to verify this on every CI run, but if you are debugging a script locally, follow these steps to verify:
|
|
||||||
|
|
||||||
1. Run the follwing command from within the `python` of the virtual environment:
|
|
||||||
|
|
||||||
````
|
|
||||||
```python
|
|
||||||
import site
|
|
||||||
print(site.getsitepackages())
|
|
||||||
```
|
|
||||||
````
|
|
||||||
|
|
||||||
2. Verify that those directories do not contain a `qiskit` directory. If they do, you likely have namespace-extending packages installed, and you should find these and remove the dependency.
|
|
||||||
|
|
||||||
3. Install the target version of Qiskit 1.0 with one of these commands:
|
|
||||||
|
|
||||||
- After the desired release candidate has been published:
|
|
||||||
```bash
|
|
||||||
pip install 'qiskit==1.0.0rc1'
|
|
||||||
```
|
|
||||||
- For a `main`-branch dependency (or substitute whatever `git` revision identifier you prefer after the `@`).
|
|
||||||
```bash
|
|
||||||
pip install 'git+https://github.com/Qiskit/qiskit.git@main'
|
|
||||||
```
|
|
||||||
|
|
||||||
You now have an environment that Qiskit allows you to test in. If `import qiskit` results in an `ImportError`, or if you are struggling to find your dependencies, see the advice in the section about the [invalid-environment protections](#qiskit-1.0-import-error) in Qiskit.
|
|
||||||
|
|
||||||
#### Sample manual GitHub Actions workflows
|
|
||||||
|
|
||||||
The following workflows set up a scheduled job to run overnight. This job sets up a testing environment for Qiskit 1.0 and runs `pytest` (or whatever test steps you need).
|
|
||||||
|
|
||||||
For a package that has no transitive dependencies `qiskit<1`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 3 * * *'
|
|
||||||
jobs:
|
|
||||||
test_main:
|
|
||||||
name: Test Qiskit main
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.10'
|
|
||||||
- name: Create environment
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
# First ensure the standard tools are up-to-date.
|
|
||||||
python -m pip install --upgrade pip wheel setuptools
|
|
||||||
# Note that this resolves everything in a single command.
|
|
||||||
# If it fails, at least one package likely requires `qiskit<1`.
|
|
||||||
python -m pip install --upgrade \
|
|
||||||
-c constraints.txt \
|
|
||||||
-r requirements-dev.txt \
|
|
||||||
. \
|
|
||||||
'git+https://github.com/Qiskit/qiskit.git@main'
|
|
||||||
- name: Run tests
|
|
||||||
run: pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
For a package that has unavoidable transitive dependencies that pin `qiskit<1`, build an invalid environment:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 3 * * *'
|
|
||||||
jobs:
|
|
||||||
test_main:
|
|
||||||
name: Test Qiskit main
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.10'
|
|
||||||
- name: Create environment
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
python -m pip install --upgrade pip wheel setuptools
|
|
||||||
# Install the regular test environment.
|
|
||||||
python -m pip install --upgrade \
|
|
||||||
-c constraints.txt \
|
|
||||||
-r requirements-dev.txt \
|
|
||||||
.
|
|
||||||
# Uninstall `qiskit` and `qiskit-terra`.
|
|
||||||
python -m pip uninstall --yes qiskit qiskit-terra
|
|
||||||
# Install the new version of Qiskit
|
|
||||||
python -m pip install 'git+https://github.com/Qiskit/qiskit.git@main'
|
|
||||||
- name: Run tests
|
|
||||||
run: pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Sample `tox` configuration
|
|
||||||
|
|
||||||
The following are examples of `tox.ini` sections to build a testing environment for Qiskit 1.0 and run `pytest` (or whatever test steps you need).
|
|
||||||
|
|
||||||
If nothing prevents Qiskit 1.0 from being installed in a valid environment:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[tox]
|
|
||||||
minversion = 4.0.0
|
|
||||||
|
|
||||||
# This environment section should set up your regular test build.
|
|
||||||
# We'll extend it after, and this one is just an example.
|
|
||||||
[testenv]
|
|
||||||
install_command = pip install -c {toxinidir}/constraints.txt -U {opts} {packages}
|
|
||||||
deps =
|
|
||||||
-r{toxinidir}/requirements-dev.txt
|
|
||||||
commands =
|
|
||||||
pytest
|
|
||||||
|
|
||||||
# This is an override environment to install Qiskit main.
|
|
||||||
# We're assuming that you have a requirement like `qiskit>=0.45`
|
|
||||||
# in your packages metadata requirements.
|
|
||||||
[testenv:qiskit-main]
|
|
||||||
# Inherit the base dependencies, and add the additional requirement.
|
|
||||||
deps =
|
|
||||||
[{testenv}deps]
|
|
||||||
git+https://github.com/Qiskit/qiskit@main
|
|
||||||
# All other options, like the `commands` section, are inherited from `testenv`.
|
|
||||||
```
|
|
||||||
|
|
||||||
If your package or a transitive dependency has an unavoidable pin on `qiskit<1`, we recommend doing this testing using the manual environment construction as in the above section, because `tox` introduces several complexities by being more strict about environment isolation and installation order.
|
|
||||||
This is correct behavior by `tox` (we shouldn't construct an invalid environment), but because we already know we're building an invalid environment, these checks get in the way.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[tox]
|
|
||||||
minversion = 4.0.0
|
|
||||||
|
|
||||||
# This environment section should set up your regular test build.
|
|
||||||
# We'll extend it later. This is just an example.
|
|
||||||
[testenv]
|
|
||||||
install_command = pip install -c {toxinidir}/constraints.txt -U {opts} {packages}
|
|
||||||
deps =
|
|
||||||
-r{toxinidir}/requirements-dev.txt
|
|
||||||
commands =
|
|
||||||
pytest
|
|
||||||
|
|
||||||
[testenv:qiskit-main]
|
|
||||||
# Set a sequence of commands to run in the environment after everything has been installed,
|
|
||||||
# but before the main test suite.
|
|
||||||
commands_pre =
|
|
||||||
pip uninstall --yes qiskit qiskit-terra
|
|
||||||
pip install 'git+https://github.com/Qiskit/qiskit@main'
|
|
||||||
# All other sections, like the dependencies and the 'commands' section are inherited.
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="why-did-this-happen"></span>
|
|
||||||
## Why these changes happened
|
|
||||||
|
|
||||||
This section contains detailed information about pre-1.0 Qiskit packaging and why we made the breaking packaging change.
|
|
||||||
|
|
||||||
We know that the change is inconvenient, but this restores Qiskit to the simple package structure that most Python packages use, which will be easier for users, developers, and library authors after the Qiskit 1.0 transition is complete.
|
|
||||||
|
|
||||||
<Admonition type="info" title="Python packaging terminology">
|
|
||||||
This section uses some Python-packaging jargon to better explain what was happening.
|
|
||||||
The following words have special meanings:
|
|
||||||
|
|
||||||
- _module_: A single Python file.
|
|
||||||
|
|
||||||
- _package_: A directory containing an `__init__.py` and other files or packages that Python can read.
|
|
||||||
This is the actual code as installed on your system, and is what executes when you run `import something`.
|
|
||||||
Python considers any directory that is on the search path to be something you can import (and will import many additional items).
|
|
||||||
|
|
||||||
This is not the same object that you `pip install` (which is a _distribution_), but typically what you `pip install` and what you `import` have the same name.
|
|
||||||
|
|
||||||
- _submodule_, _subpackage_: These are imprecise terms, but are commonly used.
|
|
||||||
The _sub_ part means "contained inside a package".
|
|
||||||
A submodule is a module and a subpackage is a package, but they are part of a larger package.
|
|
||||||
|
|
||||||
- _namespace package_: A package that can have submodules or subpackages installed into it by other _distributions_.
|
|
||||||
Critically, no one distribution contributing to a namespace package necessarily owns all the installed files, so it can be tricky to completely uninstall
|
|
||||||
or upgrade one.
|
|
||||||
|
|
||||||
- _distribution_: The compressed Python files, data files, and metadata that are downloaded when you run `pip install something`.
|
|
||||||
Often, a distribution contains exactly one package and the metadata about how to install it (its requirements and so on), but this is not required.
|
|
||||||
A distribution can contain zero or more modules or packages.
|
|
||||||
|
|
||||||
If you are familiar with "package managers" outside the context of Python, such as `apt` from Debian/Ubuntu or Homebrew on macOS, then what they call a "package", Python calls a distribution, and there is no exact match for what Python calls a package.
|
|
||||||
|
|
||||||
Most sources talking about Python packaging use the term _package_ to mean both distributions and packages, and you must refer to the context to understand what is meant.
|
|
||||||
In general, if you `import` it, the source means "package", and if you `pip install` it, the source means "distribution".
|
|
||||||
|
|
||||||
- _search path_: When trying to `import something`, Python searches a predefined list of places for a module or package called `something`.
|
|
||||||
The list of places is the _search path_.
|
|
||||||
You can see and modify the search path in `sys.path`.
|
|
||||||
|
|
||||||
- _requirement_: A distribution contains information on other distributions it depends on when installed.
|
|
||||||
Any other distribution that is necessary is a _requirement_, and the package manager (usually `pip` or `conda`) should ensure that all requirements are installed with compatible versions.
|
|
||||||
|
|
||||||
Python is highly dynamic, and many complexities can arise; for example, it's possible that a module or package does not correspond to files on disk, or that they are compiled extensions.
|
|
||||||
The search path is not only a search over directories, but for this discussion, only files on disk are relevant.
|
|
||||||
Further complications aren't necessary to understand the problems described in this section, so you can use the model described above.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### The old Qiskit structure
|
|
||||||
|
|
||||||
Historically, Qiskit was comprised of many Python distributions: `qiskit-terra`, the compiler core; `qiskit-aer`, the high-performance simulator; the original IBM Quantum provider; and several now-obsolete packages providing particular exploratory algorithmic or experiment-running features.
|
|
||||||
For user ease, we also provided a Python distribution called `qiskit`, which contained no code of its own, but caused all the other components to be installed.
|
|
||||||
We called this the _metapackage_, by analogy to similar concepts in other package managers.
|
|
||||||
The code of the core of Qiskit lived in `qiskit-terra`, which owned the root of the Python package `qiskit`. In other words, `qiskit-terra` controlled what happened when you ran `import qiskit`.
|
|
||||||
Until Qiskit 1.0, the `qiskit` package was a namespace package and contained a second namespace package at `qiskit.providers`.
|
|
||||||
|
|
||||||
This organization caused us and our users quite a few problems.
|
|
||||||
|
|
||||||
For example, downstream libraries that depended on Qiskit often only actually needed the compiler core, and did not require the rest of the large ecosystem that came with `pip install qiskit`.
|
|
||||||
They would therefore correctly specify their requirement as `qiskit-terra`.
|
|
||||||
However, when people tried to uninstall Qiskit by running `pip uninstall qiskit`, `pip` encountered problems:
|
|
||||||
|
|
||||||
- `pip` does not remove distributions that are now unused. So `pip uninstall qiskit` did almost nothing; there was no code in the distribution, so no code was removed.
|
|
||||||
- Even if it were to remove code, many downstream distributions would remain installed because they depended on `qiskit-terra`.
|
|
||||||
- Even if `qiskit-terra` was uninstalled, it might still leave an importable `qiskit` directory with no usable code, because it was a namespace package.
|
|
||||||
|
|
||||||
When installing or upgrading distributions with a `pip install` command, `pip` also does not take into account previous requirement resolutions.
|
|
||||||
Because there were two packages, upgrading a package that required `qiskit-terra` to be upgraded caused an invalid environment; `pip` upgraded `qiskit-terra` but left `qiskit` untouched.
|
|
||||||
It issued a warning on this and all subsequent `pip install` commands, but because nothing appeared broken, users typically ignored the warning, and `pip` did not raise an error status or forbid operations.
|
|
||||||
|
|
||||||
Over time, we removed elements from the `qiskit` metapackage until, starting with Qiskit 0.44, only `qiskit-terra` remains.
|
|
||||||
Of these components, `qiskit-aer` still exists and is actively updated, but it is now installed as a separate distribution.
|
|
||||||
|
|
||||||
Similarly, we ever more strongly discouraged other libraries from using the namespace hooks.
|
|
||||||
We removed the last Qiskit use of the hooks in non-obsolete packages with the release of Qiskit Aer 0.11 and its new `qiskit_aer` Python package, although until Qiskit 1.0 we also forced the namespace path `qiskit.providers.aer` to work.
|
|
||||||
Starting with Qiskit 1.0, we have removed the ability for packages to extend any `qiskit` namespace. Thus, `pip uninstall` on the correct distribution in a valid environment now works as expected.
|
|
||||||
|
|
||||||
### The new Qiskit structure
|
|
||||||
|
|
||||||
Starting with version 1.0, Qiskit comprises a single distribution, called `qiskit`, which installs one single package, also called `qiskit`, which owns all the code contained in its directory.
|
|
||||||
This is the normal structure of Python code, and is the simplest and least error-prone structure.
|
|
||||||
|
|
||||||
The `qiskit-terra` distribution on PyPI will never be updated to version 1.0 or beyond; it is entirely superseded by `qiskit`.
|
|
||||||
The name `qiskit-terra` is no longer involved in the installation.
|
|
||||||
However, the `qiskit-terra` package is not being removed from PyPI, and we will leave its most recent version in a working state, so old scientific code and legacy packages can more easily continue to use it.
|
|
||||||
|
|
||||||
Unfortunately, because of the metapackage legacy and deficiencies in `pip` as a package manager, it is not possible for us to make a completely smooth upgrade path for users to Qiskit 1.0, especially while some packages depend on earlier versions of Qiskit, and some require only Qiskit 1.0+.
|
|
||||||
These problems will lessen as more of the ecosystem migrates to Qiskit 1.0.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
We will not make similar breaking packaging changes in the future.
|
|
||||||
This is a one-time event, at the release of Qiskit 1.0, specifically so that our packaging story will be as easy as possible in the future.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="troubleshooting"></span>
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
The packaging changes around Qiskit 1.0 are tricky, and Python's standard tool `pip` is not rich enough in some ways for us to communicate the changes in the distribution structures to it, which unfortunately might cause issues for users.
|
|
||||||
We have tried to make Qiskit fail quickly and loudly if it detects an invalid environment, without false positives.
|
|
||||||
We understand that users might find it annoying to get the error message, but in our experience, it's much better to be aware of the problem right away than for things to appear to be working on the surface, only to fail in subtle ways in the future.
|
|
||||||
|
|
||||||
This section contains packaging errors that you might see, and describes how to resolve them.
|
|
||||||
|
|
||||||
Most of these problems are not unique to Qiskit, so the advice is likely relevant, even if the problematic parts are not related to Qiskit.
|
|
||||||
|
|
||||||
### `import qiskit` says "ModuleNotFoundError: No module named 'qiskit'"
|
|
||||||
|
|
||||||
Python cannot find your Qiskit installation.
|
|
||||||
|
|
||||||
If you definitely installed Qiskit, then you probably do not have the correct virtual environment activated.
|
|
||||||
See the [section on activating a virtual environment](#activating-a-venv) for instructions.
|
|
||||||
|
|
||||||
If you are using Jupyter and see this, ensure that Jupyter is installed into the same virtual environment as Qiskit.
|
|
||||||
Exit Jupyter, activate the Qiskit virtual environment on the command line, run `pip install jupyterlab` (or whichever notebook interface you use), then reopen Jupyter.
|
|
||||||
|
|
||||||
### `import qiskit` succeeds, but trying to do anything returns "AttributeError: module 'qiskit' has no attribute '...'"
|
|
||||||
|
|
||||||
This likely means that your environment had an old version of Qiskit in it alongside a package that extended its namespace (such as old versions of Qiskit Aer, or the long-obsolete Qiskit IBMQ Provider), and then Qiskit was uninstalled.
|
|
||||||
The easiest thing to do is to start a new virtual environment, and only install recent, non-obsolete packages into it.
|
|
||||||
|
|
||||||
If you have just started a new virtual environment, or you're sure that legacy packages are not the problem, make sure that your current working directory (the directory your shell session was in when you launched Python / Jupyter) does not contain a folder called `qiskit`.
|
|
||||||
Python's default rules search the current working directory very early in the search path when trying to `import` a module, so a directory with a duplicate name can cause import problems.
|
|
||||||
|
|
||||||
<span id="pip-resolution-impossible"></span>
|
|
||||||
### `pip` refuses to install some packages together
|
|
||||||
|
|
||||||
After running a `pip install` command with many items on it, you might see an error such as:
|
|
||||||
|
|
||||||
```text
|
|
||||||
ERROR: Cannot install qiskit-dynamics==0.4.4 and qiskit==1.0.0 because these package versions have conflicting dependencies.
|
|
||||||
|
|
||||||
The conflict is caused by:
|
|
||||||
The user requested qiskit==1.0.0
|
|
||||||
qiskit-dynamics 0.4.4 depends on qiskit<1.0
|
|
||||||
|
|
||||||
To fix this you could try to:
|
|
||||||
1. loosen the range of package versions you've specified
|
|
||||||
2. remove package versions to allow pip attempt to solve the dependency conflict
|
|
||||||
|
|
||||||
ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts
|
|
||||||
```
|
|
||||||
|
|
||||||
This describes a true resolution conflict; there is no valid way to install all of these distributions at the same time.
|
|
||||||
|
|
||||||
In the context of Qiskit 1.0, this is likely because one of the distributions you are trying to install contains a requirement like `qiskit<1.0`.
|
|
||||||
This means that the developers of that distribution have marked it as not (yet) compatible with Qiskit 1.0.
|
|
||||||
|
|
||||||
You can (politely) ask those developers when they will release a new version of their package that is compatible with Qiskit 1.0, but first check that they have no open issue or pull request already asking for this wherever they accept comments.
|
|
||||||
Be mindful that this takes time; please give the developers a month or so to prepare new versions of their distributions!
|
|
||||||
Until then, you cannot install that distribution alongside Qiskit 1.0.
|
|
||||||
To continue using that distribution, create a new virtual environment and use Qiskit 0.45 or 0.46 (or whichever version it supports) alongside that other package.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
If you get this error, **do not** try to build the environment by calling `pip install` several times.
|
|
||||||
Those commands will probably not fail, but you will have created an invalid environment.
|
|
||||||
You would likely then see some of the other error messages described in this section.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
You can also read [the documentation from the Python packaging authority about conflict resolution](https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts).
|
|
||||||
|
|
||||||
### `pip` succeeds but prints errors after running `pip install` commands
|
|
||||||
|
|
||||||
You might see an error in the output of `pip`, such as the following:
|
|
||||||
|
|
||||||
```text
|
|
||||||
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behavior is the source of the following dependency conflicts.
|
|
||||||
some-distribution 0.4.4 requires qiskit>=0.44,<1, but you have qiskit 1.0.0 which is incompatible.
|
|
||||||
```
|
|
||||||
|
|
||||||
The top line usually appears verbatim (as of `pip` 23.3), but second line changes depending on the exact problem, and there may be several lines like it.
|
|
||||||
`pip` is likely to then indicate that it did whatever you wanted successfully, despite the error message.
|
|
||||||
|
|
||||||
This means that the environment is in conflict and you cannot be sure that it will work correctly.
|
|
||||||
To solve the problem, examine the list of messages from `pip` and determine if you need all of the packages that have conflicting requirements.
|
|
||||||
Sometimes there will be true conflicts between dependencies; you might need multiple virtual environments to separate out dependencies that have incompatible requirements.
|
|
||||||
|
|
||||||
The safest choice is to begin a new virtual environment (or more than one, if there are true conflicts), then delete the one in conflict.
|
|
||||||
|
|
||||||
When setting up virtual environments, run only one `pip install` command that includes all the dependencies you need.
|
|
||||||
This is the most reliable way for `pip` to find a properly resolved environment with no conflicts.
|
|
||||||
If you keep having problems with conflicts after setting up environments, avoid running any further `pip install` or `pip uninstall` commands; `pip` does not guarantee to keep the environment coherent on subsequent commands.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If you are concerned about working with multiple virtual environments, rest assured that Python development and use often involve several virtual environments. It's common and good practice to create new ones to work on separate projects.
|
|
||||||
When you're done with a virtual environment, you can simply delete its directory; there is no reason to keep multiple environments permanently.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="qiskit-1.0-import-error"></span>
|
|
||||||
### `import qiskit` raises `ImportError`
|
|
||||||
|
|
||||||
When running `import qiskit`, you might see an error such as:
|
|
||||||
|
|
||||||
> ImportError: Qiskit is installed in an invalid environment that has both Qiskit 1.0+ and an earlier version.
|
|
||||||
> You should create a new virtual environment, and ensure that you do not mix dependencies between Qiskit pre-1.0 and post-1.0.
|
|
||||||
> Any packages that depend on 'qiskit-terra' are not compatible with Qiskit 1.0 and will need to be updated.
|
|
||||||
> Qiskit unfortunately cannot enforce this requirement during environment resolution.
|
|
||||||
|
|
||||||
<Admonition type="tip">
|
|
||||||
You might have run a completely valid `pip install` command, following all the recommendations in this guide, and still see this error message.
|
|
||||||
This is not your fault, but the error message is still correct, and Qiskit cannot safely load.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
The error means that Qiskit is installed in an invalid environment that includes both Qiskit 1.0 and an earlier version.
|
|
||||||
This is characterized by the `qiskit-terra` distribution being installed alongside Qiskit 1.0.
|
|
||||||
You can check what distributions are installed by running `pip list`, but you cannot fix this by simply uninstalling `qiskit-terra`.
|
|
||||||
|
|
||||||
Unfortunately, `qiskit>=1.0` and `qiskit-terra` are conflicting distributions, and cannot both be installed together.
|
|
||||||
Even more unfortunately, _we cannot communicate this conflict to `pip`_ because of limitations in its metadata system.
|
|
||||||
|
|
||||||
This error most frequently arises in one of two situations:
|
|
||||||
|
|
||||||
- You ran something like `pip install 'qiskit>=1' something-else`, and `something-else` has a requirement on `qiskit-terra`.
|
|
||||||
- You tried to run `pip install -U qiskit` in an existing environment.
|
|
||||||
|
|
||||||
In both of these cases, there is no guarantee that `pip` will return a helpful message to you.
|
|
||||||
|
|
||||||
<Admonition type="tip">
|
|
||||||
One way to require `pip` to forbid `qiskit-terra` from individual `install` commands is to use [a constraints file](https://pip.pypa.io/en/stable/user_guide/#constraints-files) that requires that `qiskit-terra` is set to an impossible version.
|
|
||||||
For example, a constraints file that includes the line `qiskit-terra>=1.0` will mean that if a dependency attempts to install `qiskit-terra`, no published versions will match the requirements.
|
|
||||||
|
|
||||||
We have provided such a file in a GitHub Gist at <https://qisk.it/1-0-constraints>, which you can use like this:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -c https://qisk.it/1-0-constraints qiskit [other packages]
|
|
||||||
```
|
|
||||||
|
|
||||||
If a package requires `qiskit-terra`, you will see [a resolution failure](#pip-resolution-impossible).
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="debug-venv-for-1.0"></span>
|
|
||||||
#### Create a working environment for Qiskit 1.0
|
|
||||||
|
|
||||||
No matter how this happened, it is much easier to make a new virtual environment.
|
|
||||||
|
|
||||||
First, we need to find out which packages are introducing a dependency on `qiskit-terra`.
|
|
||||||
Using the broken environment, install `pipdeptree` from PyPI. This is a tool for generating dependency graphs:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install pipdeptree
|
|
||||||
```
|
|
||||||
|
|
||||||
Ask it which packages are introducing dependencies on `qiskit-terra` and `qiskit` (these are two separate commands):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pipdeptree --reverse --package qiskit-terra
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pipdeptree --reverse --package qiskit
|
|
||||||
```
|
|
||||||
|
|
||||||
The outputs might look something like:
|
|
||||||
|
|
||||||
```text
|
|
||||||
qiskit-terra==0.45.2
|
|
||||||
└── qiskit-dynamics==0.4.2 [requires: qiskit-terra>=0.23.0]
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
qiskit==1.0.0
|
|
||||||
├── qiskit-aer==0.13.2 [requires: qiskit>=0.45.0]
|
|
||||||
└── qiskit-ibm-provider==0.8.0 [requires: qiskit>=0.45.0]
|
|
||||||
```
|
|
||||||
|
|
||||||
In the above example, we have two distributions that have declared themselves compatible with Qiskit 1.0 (`qiskit-aer` and `qiskit-ibm-provider`), and one that still has a dependency on `qiskit-terra`.
|
|
||||||
|
|
||||||
<Admonition type="tip">
|
|
||||||
This example is a flat dependency structure.
|
|
||||||
You might see a much deeper tree than this.
|
|
||||||
The packages that are directly dependent on `qiskit-terra` (lowest indentation) are most likely to be the problematic ones, but one farther down the tree could be problematic if it depends on a specific old version of some other package that has already been updated.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Seeing a dependency on `qiskit-terra` can mean one of a few things:
|
|
||||||
|
|
||||||
- The dependent is an old package, and will not be updated to support Qiskit 1.0.
|
|
||||||
|
|
||||||
In this case, there is no chance of using the package with Qiskit 1.0, and you will need to continue using a previous version of Qiskit.
|
|
||||||
Typically this is characterized by the dependent being at its latest version (assuming the environment is new, and you didn't pin it lower) and having a direct requirement on `qiskit-terra`.
|
|
||||||
|
|
||||||
- The dependent is a package that is actively maintained, but does not yet support Qiskit 1.0.
|
|
||||||
|
|
||||||
In this case, you will need to wait for the developers to release a compatible version - please be patient!
|
|
||||||
Typically this is characterized by the installed distribution _not_ being at its latest version, even though your installation command did not specify a version.
|
|
||||||
You can check the latest release version of the distribution by finding its page on https://pypi.org/.
|
|
||||||
|
|
||||||
`pip` likely searched old versions of the package until it found one (possibly from months or years ago) that depended only on `qiskit-terra`.
|
|
||||||
|
|
||||||
This is what has happened in the example above. At the time this document was created, `qiskit-dynamics==0.4.4` was the latest release version.
|
|
||||||
|
|
||||||
If you constructed this environment out of several `pip install` commands (such as if the environment is old and has been updated), first try to install all of your packages by using a single `pip install` command when you build a new environment.
|
|
||||||
If the problem persists, at least one of the packages you want likely does not support Qiskit 1.0 yet, and `pip` is finding an old version that it believes will work because it doesn't know about the `qiskit>=1`/`qiskit-terra` conflict.
|
|
||||||
|
|
||||||
Instead, use the `pipdeptree` commands to identify which dependencies do not yet support Qiskit 1.0.
|
|
||||||
Exclude any packages that do not yet support Qiskit 1.0 when constructing a Qiskit 1.0 environment, or continue to use a prior version of Qiskit.
|
|
||||||
See [Create the new environment](#creating-a-venv) for instructions.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The example in this section was generated before Qiskit 1.0 was released.
|
|
||||||
|
|
||||||
The "old" distribution in question (`qiskit-dynamics`) was behaving correctly; it was not known to support Qiskit 1.0 yet, so it marked that in its requirements.
|
|
||||||
It's not possible to backdate requirements changes to previously released versions, and `pip` will search arbitrarily far back to locate something that works when building an environment.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="debug-venv-for-0.45"></span>
|
|
||||||
#### Create a working environment for Qiskit 0.45 or 0.46
|
|
||||||
|
|
||||||
If you have a broken environment after trying to install Qiskit 0.45 or 0.46, the most likely situation is that `pip` installed Qiskit 1.0 because it tried to pick the latest versions of packages, even though it was not required.
|
|
||||||
The easiest way to fix this is to create a new virtual environment, then run a single `pip install` command that has all the packages you need, plus an explicit `'qiskit<1'` entry.
|
|
||||||
If `pip` successfully resolves this dependency graph, you should have a working virtual environment.
|
|
||||||
If at least one distribution requires Qiskit 1.0 or greater, `pip` should give you an error message explaining this, which looks like the one in [the section on failed resolutions](#pip-resolution-impossible).
|
|
||||||
|
|
||||||
You can also use the `pipdeptree` commands listed in [Create a working environment for Qiskit 1.0](#debug-venv-for-1.0) from within the broken environment to determine which distributions have an explicit requirement on `qiskit>=1`.
|
|
||||||
|
|
||||||
#### I'm a developer, my environments are definitely right, and I'm still getting the error
|
|
||||||
|
|
||||||
First: you must be _absolutely_ certain that your environments are correct.
|
|
||||||
The test that Qiskit uses to determine a broken environment is quite robust; specifically, it queries `importlib.metadata` for distribution information on installed packages and checks the version numbers returned.
|
|
||||||
The Qiskit 1.0 side of the test also checks for sentinel files that were present in old Qiskit versions and not Qiskit 1.0.
|
|
||||||
|
|
||||||
If you are a Qiskit developer, it's possible that you have old `qiskit.egg-info` or `qiskit-terra.egg-info` (or `*.dist-info`) directories present on your meta path (see `sys.meta_path`), left over from old editable installations.
|
|
||||||
In particular, check your working directory for any `*.egg-info` and `*.dist-info` directories.
|
|
||||||
If they're in the root of one of your checked out repositories, you can delete them. The worst that can happen is you might need to `pip install -e .` again, and even that is unlikely, because these are typically just part of the `setuptools` build process that doesn't get cleaned up.
|
|
||||||
|
|
||||||
If the above information does not help you and you are 100% sure that your environment is sound (or you are deliberately trying to test a broken environment):
|
|
||||||
|
|
||||||
1. [Create an issue in Qiskit](https://github.com/Qiskit/qiskit/issues/new/choose) explaining how this happened and why you are sure the environment is correct so we can fix it.
|
|
||||||
2. You can suppress the exception by setting the environment variable `QISKIT_SUPPRESS_1_0_IMPORT_ERROR=1`.
|
|
|
@ -1,849 +0,0 @@
|
||||||
---
|
|
||||||
title: qiskit.algorithms migration guide
|
|
||||||
description: Use the new interface for `qiskit.algorithms`
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithms migration guide
|
|
||||||
|
|
||||||
In Qiskit 0.44 and later releases, the `qiskit.algorithms` module has been superseded by a new standalone library, `qiskit_algorithms`,
|
|
||||||
available on [GitHub](https://github.com/qiskit-community/qiskit-algorithms) and
|
|
||||||
[PyPi](https://pypi.org/project/qiskit-algorithms). The `qiskit.algorithms` module was migrated to a
|
|
||||||
separate package in order to clarify the purpose of Qiskit and make a distinction between the tools and libraries built on top of it.
|
|
||||||
|
|
||||||
If your code used `qiskit.algorithms`, follow these steps:
|
|
||||||
|
|
||||||
1. Check your code for any uses of the `qiskit.algorithms` module. If you are, follow this guide to
|
|
||||||
migrate to the primitives-based implementation.
|
|
||||||
2. After updating your code, run `pip install qiskit-algorithms` and update your imports from
|
|
||||||
`qiskit.algorithms` to `qiskit_algorithms`.
|
|
||||||
|
|
||||||
## Background
|
|
||||||
|
|
||||||
The [`qiskit.algorithms`](../qiskit/0.44/algorithms) module was originally built on top of the [`qiskit.opflow`](../qiskit/0.44/opflow) library and the
|
|
||||||
[`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) utility. The development of the [`qiskit.primitives`](../qiskit/primitives)
|
|
||||||
introduced a higher-level execution paradigm, with the `Estimator` for computing expectation values for observables, and `Sampler` for executing circuits and returning probability distributions. These tools allowed the [`qiskit.algorithms`](../qiskit/0.44/algorithms) module to be refactored, after which,
|
|
||||||
[`qiskit.opflow`](../qiskit/0.44/opflow) and [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) were deprecated.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
The transition away from [`qiskit.opflow`](../qiskit/0.44/opflow) affects the classes that algorithms use as part of the problem
|
|
||||||
setup. Most [`qiskit.opflow`](../qiskit/0.44/opflow) dependencies have a direct [`qiskit.quantum_info`](../qiskit/quantum_info)
|
|
||||||
replacement. One common example is the class [`qiskit.opflow.primitive_ops.PauliSumOp`](../qiskit/0.44/qiskit.opflow.primitive_ops.PauliSumOp), used to define Hamiltonians
|
|
||||||
(for example, to plug into VQE), which can be replaced by [`qiskit.quantum_info.SparsePauliOp`](../qiskit/qiskit.quantum_info.SparsePauliOp).
|
|
||||||
For information to migrate other [`qiskit.opflow`](../qiskit/0.44/opflow) objects, refer to the [Opflow migration guide](./qiskit-opflow-module).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
For further background and detailed migration steps, see these guides:
|
|
||||||
|
|
||||||
- [Opflow migration guide](./qiskit-opflow-module)
|
|
||||||
- [QuantumInstance migration guide](./qiskit-quantum-instance)
|
|
||||||
|
|
||||||
## What has changed
|
|
||||||
|
|
||||||
The [`qiskit.algorithms`](../qiskit/0.44/algorithms) module has been fully refactored to use the [`qiskit.primitives`](../qiskit/primitives), for circuit execution, instead of the [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), which is now deprecated.
|
|
||||||
|
|
||||||
There have been three types of refactoring:
|
|
||||||
|
|
||||||
1. Algorithms that were refactored in a new location to support [`qiskit.primitives`](../qiskit/primitives). These algorithms have the same
|
|
||||||
class names as the [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance)-based ones but are in a new subpackage.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
Be careful with import paths. The legacy algorithms can still be imported from
|
|
||||||
[`qiskit.algorithms`](../qiskit/0.44/algorithms). Until the legacy imports are removed, this convenience import is not available
|
|
||||||
for the refactored algorithms. Thus, to import the refactored algorithms you must specify the full import path. For example, `from qiskit.algorithms.eigensolvers import VQD`.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
- [Minimum Eigensolvers](#minimum-eigensolvers)
|
|
||||||
- [Eigensolvers](#eigensolvers)
|
|
||||||
- [Time Evolvers](#time-evolvers)
|
|
||||||
|
|
||||||
2. Algorithms that were refactored in-place (same namespace) to support both [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) and
|
|
||||||
[`qiskit.primitives`](../qiskit/primitives). In the future, [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) will be removed.
|
|
||||||
|
|
||||||
- [Amplitude Amplifiers](#amplitude-amplifiers)
|
|
||||||
- [Amplitude Estimators](#amplitude-estimators)
|
|
||||||
- [Phase Estimators](#phase-estimators)
|
|
||||||
|
|
||||||
3. Algorithms that were deprecated and are now removed entirely from [`qiskit.algorithms`](../qiskit/0.44/algorithms). These are algorithms that do not serve
|
|
||||||
as building blocks for applications and are only valueable for education, as described in the following tutorials:
|
|
||||||
|
|
||||||
- [Linear Solvers (HHL)](https://github.com/Qiskit/textbook/blob/main/notebooks/ch-applications/hhl_tutorial.ipynb) ,
|
|
||||||
- [Factorizers (Shor)](https://github.com/Qiskit/textbook/blob/main/notebooks/ch-algorithms/shor.ipynb)
|
|
||||||
|
|
||||||
This migration guide focuses on the algorithms with migration alternatives within
|
|
||||||
[`qiskit.algorithms`](../qiskit/0.44/algorithms), that is, refactoring types 1 and 2.
|
|
||||||
|
|
||||||
## How to choose a primitive configuration for your algorithm
|
|
||||||
|
|
||||||
The classes in
|
|
||||||
[`qiskit.algorithms`](../qiskit/0.44/algorithms) are initialized with any implementation of [`qiskit.primitives.BaseSampler`](../qiskit/qiskit.primitives.BaseSampler) or [`qiskit.primitives.BaseEstimator`](../qiskit/qiskit.primitives.BaseEstimator).
|
|
||||||
|
|
||||||
Once you know which primitive you want to use, choose the primitive implementation that meets your needs. For example:
|
|
||||||
|
|
||||||
- For quick prototyping, use the reference implementations of primitives included in Qiskit: [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler) and [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator).
|
|
||||||
|
|
||||||
- For finer algorithm tuning, use a local simulator such as the primitive implementation in Aer: [`qiskit_aer.primitives.Sampler`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Sampler.html) and [`qiskit_aer.primitives.Estimator`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Estimator.html).
|
|
||||||
|
|
||||||
- For running on quantum hardware choose from these options:
|
|
||||||
|
|
||||||
- Access services with native primitive implementations, such as the IBM Qiskit Runtime service by using [`qiskit_ibm_runtime.Sampler`](../qiskit-ibm-runtime/qiskit_ibm_runtime.Sampler) and [`qiskit_ibm_runtime.Estimator`.](../qiskit-ibm-runtime/qiskit_ibm_runtime.Estimator)
|
|
||||||
- Wrap any system with `Backend` primitives ([`qiskit.primitives.BackendSampler`](../qiskit/qiskit.primitives.BackendSampler) and [`qiskit.primitives.BackendEstimator`](../qiskit/qiskit.primitives.BackendEstimator)). These wrappers implement a primitive interface on top of a backend that only supports `backend.run()`.
|
|
||||||
|
|
||||||
For detailed information and examples, particularly on the use of the `Backend` primitives, refer to
|
|
||||||
the [QuantumInstance migration guide](./qiskit-quantum-instance).
|
|
||||||
|
|
||||||
This guide describes these common configurations for algorithms that determine which primitive import to use:
|
|
||||||
|
|
||||||
- Running an algorithm with a statevector simulator when you want the ideal outcome without shot noise. For example, using the [`qiskit.opflow`](../qiskit/0.44/opflow) legacy
|
|
||||||
[`qiskit.opflow.expectations.MatrixExpectation`](../qiskit/0.44/qiskit.opflow.expectations.MatrixExpectation):
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
- Reference Primitives with default configuration. See [QAOA](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/05_qaoa.ipynb) for an example.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler, Estimator
|
|
||||||
```
|
|
||||||
|
|
||||||
- Aer Primitives with statevector simulator. See [QAOA](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/05_qaoa.ipynb) for an example.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_aer.primitives import Sampler, Estimator
|
|
||||||
|
|
||||||
sampler = Sampler(backend_options={"method": "statevector"})
|
|
||||||
estimator = Estimator(backend_options={"method": "statevector"})
|
|
||||||
```
|
|
||||||
|
|
||||||
- Running an algorithm using a simulator or device with shot noise. For example, using the [`qiskit.opflow`](../qiskit/0.44/opflow) legacy [`qiskit.opflow.expectations.PauliExpectation`](../qiskit/0.44/qiskit.opflow.expectations.PauliExpectation):
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
- Reference primitives with shots. See the [VQE](#vqe) examples.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler, Estimator
|
|
||||||
|
|
||||||
sampler = Sampler(options={"shots": 100})
|
|
||||||
estimator = Estimator(options={"shots": 100})
|
|
||||||
|
|
||||||
# or...
|
|
||||||
sampler = Sampler()
|
|
||||||
job = sampler.run(circuits, shots=100)
|
|
||||||
|
|
||||||
estimator = Estimator()
|
|
||||||
job = estimator.run(circuits, observables, shots=100)
|
|
||||||
```
|
|
||||||
|
|
||||||
- Aer primitives with default configuration. See the [VQE](#vqe) examples.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_aer.primitives import Sampler, Estimator
|
|
||||||
```
|
|
||||||
|
|
||||||
- IBM Qiskit Runtime primitives with default configuration. See [VQD](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/04_vqd.ipynb) for an example.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Sampler, Estimator
|
|
||||||
```
|
|
||||||
|
|
||||||
- Running an algorithm on an Aer simulator using a custom instruction. For example, using the [`qiskit.opflow`](../qiskit/0.44/opflow) legacy
|
|
||||||
[`qiskit.opflow.expectations.AerPauliExpectation`](../qiskit/0.44/qiskit.opflow.expectations.AerPauliExpectation).
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
- Aer Primitives with `shots=None`, `approximation=True`. See [TrotterQRTE](#trotterqrte) for examples.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_aer.primitives import Sampler, Estimator
|
|
||||||
|
|
||||||
sampler = Sampler(run_options={"approximation": True, "shots": None})
|
|
||||||
estimator = Estimator(run_options={"approximation": True, "shots": None})
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="eigen"></span>
|
|
||||||
## Minimum Eigensolvers
|
|
||||||
|
|
||||||
The minimum eigensolver algorithms were refactored in a new location.
|
|
||||||
Instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), [`qiskit.algorithms.minimum_eigensolvers`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers) are now initialized
|
|
||||||
by using an instance of the [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler) or [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) primitive, depending
|
|
||||||
on the algorithm. The legacy classes can still be found in `qiskit.algorithms.minimum_eigen_solvers`.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
For the [`qiskit.algorithms.minimum_eigensolvers`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers) classes, depending on the import path,
|
|
||||||
you will access either the primitive-based or the quantum-instance-based implementation. You have to be careful, because the class name does not change.
|
|
||||||
|
|
||||||
- Old import (QuantumInstance-based): `from qiskit.algorithms import VQE, QAOA, NumPyMinimumEigensolver`
|
|
||||||
- New import (Primitives-based): `from qiskit.algorithms.minimum_eigensolvers import VQE, SamplingVQE, QAOA, NumPyMinimumEigensolver`
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### VQE
|
|
||||||
|
|
||||||
The legacy `qiskit.algorithms.minimum_eigen_solvers.VQE` class has now been split according to the use case:
|
|
||||||
|
|
||||||
- For general-purpose Hamiltonians, use the Estimator-based [`qiskit.algorithms.minimum_eigensolvers.VQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.VQE)
|
|
||||||
class.
|
|
||||||
- If you have a diagonal Hamiltonian and want the algorithm to return a sampling of the state, use
|
|
||||||
the new Sampler-based [`qiskit.algorithms.minimum_eigensolvers.SamplingVQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.SamplingVQE) algorithm. Previously, this was done by using the legacy `qiskit.algorithms.minimum_eigen_solvers.VQE` with
|
|
||||||
[`qiskit.opflow.expectations.CVaRExpectation`](../qiskit/0.44/qiskit.opflow.expectations.CVaRExpectation).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
In addition to taking in an [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) instance instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance),
|
|
||||||
the new [`qiskit.algorithms.minimum_eigensolvers.VQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.VQE) signature has undergone the following changes:
|
|
||||||
|
|
||||||
- The `expectation` and `include_custom` parameters have been removed, as this functionality is now
|
|
||||||
defined at the `Estimator` level.
|
|
||||||
- The `gradient` parameter now takes in an instance of a primitive-based gradient class from
|
|
||||||
[`qiskit.algorithms.gradients`](../qiskit/0.44/qiskit.algorithms.gradients) instead of the legacy [`qiskit.opflow.gradients.Gradient`](../qiskit/0.44/qiskit.opflow.gradients.Gradient) class.
|
|
||||||
- The `max_evals_grouped` parameter has been removed, as it can be set directly on the optimizer class.
|
|
||||||
- The `estimator`, `ansatz` and `optimizer` are the only parameters that can be defined positionally
|
|
||||||
(and in this order). All others have become keyword-only arguments.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The new [`qiskit.algorithms.minimum_eigensolvers.VQEResult`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.VQEResult) class does not include the state, as
|
|
||||||
this output was only useful in the case of diagonal operators. However, it is available as part of the new
|
|
||||||
[`qiskit.algorithms.minimum_eigensolvers.SamplingVQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.SamplingVQE) [`qiskit.algorithms.minimum_eigensolvers.SamplingVQEResult`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.SamplingVQEResult).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
#### VQE examples
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import VQE
|
|
||||||
from qiskit.algorithms.optimizers import SPSA
|
|
||||||
from qiskit.circuit.library import TwoLocal
|
|
||||||
from qiskit.opflow import PauliSumOp
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
|
|
||||||
ansatz = TwoLocal(2, 'ry', 'cz')
|
|
||||||
opt = SPSA(maxiter=50)
|
|
||||||
|
|
||||||
# shot-based simulation
|
|
||||||
backend = AerSimulator()
|
|
||||||
qi = QuantumInstance(backend=backend, shots=2048, seed_simulator=42)
|
|
||||||
vqe = VQE(ansatz, optimizer=opt, quantum_instance=qi)
|
|
||||||
|
|
||||||
hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
|
|
||||||
result = vqe.compute_minimum_eigenvalue(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalue)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
(-0.9775390625+0j)
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms.minimum_eigensolvers import VQE # new import!!!
|
|
||||||
from qiskit.algorithms.optimizers import SPSA
|
|
||||||
from qiskit.circuit.library import TwoLocal
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit.primitives import Estimator
|
|
||||||
from qiskit_aer.primitives import Estimator as AerEstimator
|
|
||||||
|
|
||||||
ansatz = TwoLocal(2, 'ry', 'cz')
|
|
||||||
opt = SPSA(maxiter=50)
|
|
||||||
|
|
||||||
# shot-based simulation
|
|
||||||
estimator = Estimator(options={"shots": 2048})
|
|
||||||
vqe = VQE(estimator, ansatz, opt)
|
|
||||||
|
|
||||||
# another option
|
|
||||||
aer_estimator = AerEstimator(run_options={"shots": 2048, "seed": 42})
|
|
||||||
vqe = VQE(aer_estimator, ansatz, opt)
|
|
||||||
|
|
||||||
hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
|
|
||||||
result = vqe.compute_minimum_eigenvalue(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalue)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-0.986328125
|
|
||||||
```
|
|
||||||
|
|
||||||
#### VQE applying CVaR (SamplingVQE) example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import VQE
|
|
||||||
from qiskit.algorithms.optimizers import SLSQP
|
|
||||||
from qiskit.circuit.library import TwoLocal
|
|
||||||
from qiskit.opflow import PauliSumOp, CVaRExpectation
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
|
|
||||||
ansatz = TwoLocal(2, 'ry', 'cz')
|
|
||||||
opt = SLSQP(maxiter=50)
|
|
||||||
|
|
||||||
# shot-based simulation
|
|
||||||
backend = AerSimulator()
|
|
||||||
qi = QuantumInstance(backend=backend, shots=2048)
|
|
||||||
expectation = CVaRExpectation(alpha=0.2)
|
|
||||||
vqe = VQE(ansatz, optimizer=opt, expectation=expectation, quantum_instance=qi)
|
|
||||||
|
|
||||||
# diagonal Hamiltonian
|
|
||||||
hamiltonian = PauliSumOp.from_list([("ZZ",1), ("IZ", -0.5), ("II", 0.12)])
|
|
||||||
result = vqe.compute_minimum_eigenvalue(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalue.real)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-1.38
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms.minimum_eigensolvers import SamplingVQE # new import!!!
|
|
||||||
from qiskit.algorithms.optimizers import SPSA
|
|
||||||
from qiskit.circuit.library import TwoLocal
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
from qiskit_aer.primitives import Sampler as AerSampler
|
|
||||||
|
|
||||||
ansatz = TwoLocal(2, 'ry', 'cz')
|
|
||||||
opt = SPSA(maxiter=50)
|
|
||||||
|
|
||||||
# shot-based simulation
|
|
||||||
sampler = Sampler(options={"shots": 2048})
|
|
||||||
vqe = SamplingVQE(sampler, ansatz, opt, aggregation=0.2)
|
|
||||||
|
|
||||||
# another option
|
|
||||||
aer_sampler = AerSampler(run_options={"shots": 2048, "seed": 42})
|
|
||||||
vqe = SamplingVQE(aer_sampler, ansatz, opt, aggregation=0.2)
|
|
||||||
|
|
||||||
# diagonal Hamiltonian
|
|
||||||
hamiltonian = SparsePauliOp.from_list([("ZZ",1), ("IZ", -0.5), ("II", 0.12)])
|
|
||||||
result = vqe.compute_minimum_eigenvalue(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalue.real)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-1.38
|
|
||||||
```
|
|
||||||
|
|
||||||
For complete code examples, see the following updated tutorials:
|
|
||||||
|
|
||||||
- [VQE introduction](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/01_algorithms_introduction.ipynb)
|
|
||||||
- [VQE, callback, gradients, initial point](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/02_vqe_advanced_options.ipynb)
|
|
||||||
- [VQE with Aer primitives](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/03_vqe_simulation_with_noise.ipynb)
|
|
||||||
|
|
||||||
### QAOA
|
|
||||||
|
|
||||||
The new QAOA only supports diagonal operators. This is because the legacy `qiskit.algorithms.minimum_eigen_solvers.QAOA` class extended
|
|
||||||
`qiskit.algorithms.minimum_eigen_solvers.VQE`, but now, [`qiskit.algorithms.minimum_eigensolvers.QAOA`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.QAOA)
|
|
||||||
extends [`qiskit.algorithms.minimum_eigensolvers.SamplingVQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.SamplingVQE).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
In addition to taking in a [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler) instance instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance),
|
|
||||||
the new [`qiskit.algorithms.minimum_eigensolvers.QAOA`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.QAOA) signature has undergone the following changes:
|
|
||||||
|
|
||||||
- The `expectation` and `include_custom` parameters have been removed and the `aggregation`
|
|
||||||
parameter has been added. This was previously defined through a custom `expectation` parameter.
|
|
||||||
- The `gradient` parameter now takes in an instance of a primitive-based gradient class from
|
|
||||||
[`qiskit.algorithms.gradients`](../qiskit/0.44/qiskit.algorithms.gradients) instead of the legacy [`qiskit.opflow.gradients.Gradient`](../qiskit/0.44/qiskit.opflow.gradients.Gradient) class.
|
|
||||||
- The `max_evals_grouped` parameter has been removed, as it can be set directly on the optimizer class.
|
|
||||||
- The `sampler` and `optimizer` parameters are the only parameters that can be defined positionally
|
|
||||||
(and in this order). All others have become keyword-only arguments.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If you want to run QAOA on a non-diagonal operator, use the [`qiskit.circuit.library.QAOAAnsatz`](../qiskit/qiskit.circuit.library.QAOAAnsatz) with
|
|
||||||
[`qiskit.algorithms.minimum_eigensolvers.VQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.VQE), but there will be no state result.
|
|
||||||
If your application requires the final probability distribution, instantiate a `Sampler`
|
|
||||||
and run it with the optimal circuit after [`qiskit.algorithms.minimum_eigensolvers.VQE`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.VQE).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
#### QAOA example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from qiskit.algorithms import QAOA
|
|
||||||
from qiskit.algorithms.optimizers import COBYLA
|
|
||||||
from qiskit.opflow import PauliSumOp
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
|
|
||||||
# exact statevector simulation
|
|
||||||
backend = AerSimulator()
|
|
||||||
qi = QuantumInstance(backend=backend, shots=None,
|
|
||||||
seed_simulator = 42, seed_transpiler = 42,
|
|
||||||
backend_options={"method": "statevector"})
|
|
||||||
|
|
||||||
optimizer = COBYLA()
|
|
||||||
qaoa = QAOA(optimizer=optimizer, reps=2, quantum_instance=qi)
|
|
||||||
|
|
||||||
# diagonal operator
|
|
||||||
qubit_op = PauliSumOp.from_list([("ZIII", 1),("IZII", 1), ("IIIZ", 1), ("IIZI", 1)])
|
|
||||||
result = qaoa.compute_minimum_eigenvalue(qubit_op)
|
|
||||||
|
|
||||||
print(result.eigenvalue.real)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-4.0
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms.minimum_eigensolvers import QAOA
|
|
||||||
from qiskit.algorithms.optimizers import COBYLA
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
from qiskit_aer.primitives import Sampler as AerSampler
|
|
||||||
|
|
||||||
# exact statevector simulation
|
|
||||||
sampler = Sampler()
|
|
||||||
|
|
||||||
# another option
|
|
||||||
sampler = AerSampler(backend_options={"method": "statevector"},
|
|
||||||
run_options={"shots": None, "seed": 42})
|
|
||||||
|
|
||||||
optimizer = COBYLA()
|
|
||||||
qaoa = QAOA(sampler, optimizer, reps=2)
|
|
||||||
|
|
||||||
# diagonal operator
|
|
||||||
qubit_op = SparsePauliOp.from_list([("ZIII", 1),("IZII", 1), ("IIIZ", 1), ("IIZI", 1)])
|
|
||||||
result = qaoa.compute_minimum_eigenvalue(qubit_op)
|
|
||||||
|
|
||||||
print(result.eigenvalue)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-3.999999832366272
|
|
||||||
```
|
|
||||||
|
|
||||||
For complete code examples, see the updated [QAOA tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/05_qaoa.ipynb)
|
|
||||||
|
|
||||||
### NumPyMinimumEigensolver
|
|
||||||
|
|
||||||
Because this is a classical solver, the workflow has not changed between the old and new implementation.
|
|
||||||
However, the import has changed from `qiskit.algorithms.minimum_eigen_solvers.NumPyMinimumEigensolver`
|
|
||||||
to [`qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver`](../qiskit/0.44/qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver) to conform to the new interfaces
|
|
||||||
and result classes.
|
|
||||||
|
|
||||||
#### NumPyMinimumEigensolver example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from qiskit.algorithms import NumPyMinimumEigensolver
|
|
||||||
from qiskit.opflow import PauliSumOp
|
|
||||||
|
|
||||||
solver = NumPyMinimumEigensolver()
|
|
||||||
|
|
||||||
hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
|
|
||||||
result = solver.compute_minimum_eigenvalue(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalue)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-1.4142135623730958
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms.minimum_eigensolvers import NumPyMinimumEigensolver
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
solver = NumPyMinimumEigensolver()
|
|
||||||
|
|
||||||
hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
|
|
||||||
result = solver.compute_minimum_eigenvalue(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalue)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
-1.414213562373095
|
|
||||||
```
|
|
||||||
|
|
||||||
For complete code examples, see the updated [VQE, callback, gradients, initial point tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/02_vqe_advanced_options.ipynb)
|
|
||||||
|
|
||||||
<span id="eigensolvers"></span>
|
|
||||||
## Eigensolvers
|
|
||||||
|
|
||||||
The eigensolver algorithms were refactored in a new location. Instead of using
|
|
||||||
[`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), [`qiskit.algorithms.eigensolvers`](../qiskit/0.44/qiskit.algorithms.eigensolvers) are now initialized
|
|
||||||
using an instance of the [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler) or [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) primitive, or
|
|
||||||
a primitive-based subroutine, depending on the algorithm. The legacy classes can still be found
|
|
||||||
in `qiskit.algorithms.eigen_solvers`.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
For the [`qiskit.algorithms.eigensolvers`](../qiskit/0.44/qiskit.algorithms.eigensolvers) classes, depending on the import path,
|
|
||||||
you will access either the primitive-based or the QuantumInstance-based
|
|
||||||
implementation. You have to be careful, because the class name is the same.
|
|
||||||
|
|
||||||
- Old import path (QuantumInstance): `from qiskit.algorithms import VQD, NumPyEigensolver`
|
|
||||||
- New import path (primitives): `from qiskit.algorithms.eigensolvers import VQD, NumPyEigensolver`
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### VQD
|
|
||||||
|
|
||||||
The new [`qiskit.algorithms.eigensolvers.VQD`](../qiskit/0.44/qiskit.algorithms.eigensolvers.VQD) class is initialized with an instance of the
|
|
||||||
[`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) primitive instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance).
|
|
||||||
It also takes an instance of a state fidelity class from mod:`qiskit.algorithms.state_fidelities`,
|
|
||||||
such as the [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler)-based [`qiskit.algorithms.state_fidelities.ComputeUncompute`](../qiskit/0.44/qiskit.algorithms.state_fidelities.ComputeUncompute).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
In addition to taking in a [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) instance instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance),
|
|
||||||
the new [`qiskit.algorithms.eigensolvers.VQD`](../qiskit/0.44/qiskit.algorithms.eigensolvers.VQD) signature has undergone the following changes:
|
|
||||||
|
|
||||||
- The `expectation` and `include_custom` parameters have been removed, as this functionality is now
|
|
||||||
defined at the `Estimator` level.
|
|
||||||
- The custom `fidelity` parameter has been added and the custom `gradient` parameter has
|
|
||||||
been removed because current classes in [`qiskit.algorithms.gradients`](../qiskit/0.44/qiskit.algorithms.gradients) cannot use state fidelity
|
|
||||||
gradients.
|
|
||||||
- The `max_evals_grouped` parameter has been removed because it can be set directly on the `optimizer` class.
|
|
||||||
- The `estimator`, `fidelity`, `ansatz` and `optimizer` parameters are the only parameters that can be defined positionally
|
|
||||||
(and in this order). All others have become keyword-only arguments.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Similar to VQE, the new [`qiskit.algorithms.eigensolvers.VQDResult`](../qiskit/0.44/qiskit.algorithms.eigensolvers.VQDResult) class does not include
|
|
||||||
the state. If your application requires the final probability distribution, instantiate
|
|
||||||
a `Sampler` and run it with the optimal circuit for the desired excited state
|
|
||||||
after running [`qiskit.algorithms.eigensolvers.VQD`](../qiskit/0.44/qiskit.algorithms.eigensolvers.VQD).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
#### VQD Example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import IBMQ
|
|
||||||
from qiskit.algorithms import VQD
|
|
||||||
from qiskit.algorithms.optimizers import SLSQP
|
|
||||||
from qiskit.circuit.library import TwoLocal
|
|
||||||
from qiskit.opflow import PauliSumOp
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
|
|
||||||
ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
|
|
||||||
optimizer = SLSQP(maxiter=10)
|
|
||||||
hamiltonian = PauliSumOp.from_list([("XXZ", 1), ("XYI", 1)])
|
|
||||||
|
|
||||||
# example executing in cloud simulator
|
|
||||||
provider = IBMQ.load_account()
|
|
||||||
backend = provider.get_backend("ibmq_qasm_simulator")
|
|
||||||
qi = QuantumInstance(backend=backend)
|
|
||||||
|
|
||||||
vqd = VQD(ansatz, k=3, optimizer=optimizer, quantum_instance=qi)
|
|
||||||
result = vqd.compute_eigenvalues(operator=hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalues)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Sampler, Estimator, QiskitRuntimeService, Session
|
|
||||||
from qiskit.algorithms.eigensolvers import VQD
|
|
||||||
from qiskit.algorithms.optimizers import SLSQP
|
|
||||||
from qiskit.algorithms.state_fidelities import ComputeUncompute
|
|
||||||
from qiskit.circuit.library import TwoLocal
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
|
|
||||||
optimizer = SLSQP(maxiter=10)
|
|
||||||
hamiltonian = SparsePauliOp.from_list([("XXZ", 1), ("XYI", 1)])
|
|
||||||
|
|
||||||
# example executing in cloud simulator
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum")
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
with Session(service=service, backend=backend) as session:
|
|
||||||
estimator = Estimator()
|
|
||||||
sampler = Sampler()
|
|
||||||
fidelity = ComputeUncompute(sampler)
|
|
||||||
vqd = VQD(estimator, fidelity, ansatz, optimizer, k=3)
|
|
||||||
result = vqd.compute_eigenvalues(operator=hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalues)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]
|
|
||||||
```
|
|
||||||
|
|
||||||
For complete code examples, see the updated [VQD tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/04_vqd.ipynb)
|
|
||||||
|
|
||||||
### NumPyEigensolver
|
|
||||||
|
|
||||||
Similarly to its minimum eigensolver counterpart, because this is a classical solver, the workflow has not changed
|
|
||||||
between the old and new implementation.
|
|
||||||
However, the import has changed from `qiskit.algorithms.eigen_solvers.NumPyEigensolver`
|
|
||||||
to [`qiskit.algorithms.eigensolvers.NumPyEigensolver`](../qiskit/0.44/qiskit.algorithms.eigensolvers.NumPyEigensolver) to conform to the new interfaces and result classes.
|
|
||||||
|
|
||||||
#### NumPyEigensolver Example
|
|
||||||
|
|
||||||
**[Legacy]\:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from qiskit.algorithms import NumPyEigensolver
|
|
||||||
from qiskit.opflow import PauliSumOp
|
|
||||||
|
|
||||||
solver = NumPyEigensolver(k=2)
|
|
||||||
|
|
||||||
hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
|
|
||||||
result = solver.compute_eigenvalues(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalues)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
[-1.41421356 -1.41421356]
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated]\:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms.eigensolvers import NumPyEigensolver
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
solver = NumPyEigensolver(k=2)
|
|
||||||
|
|
||||||
hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
|
|
||||||
result = solver.compute_eigenvalues(hamiltonian)
|
|
||||||
|
|
||||||
print(result.eigenvalues)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
[-1.41421356 -1.41421356]
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="time"></span>
|
|
||||||
## Time Evolvers
|
|
||||||
|
|
||||||
The time evolvers were refactored in a new location.
|
|
||||||
Instead of using a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), `qiskit.algorithms.time_evolvers` are now initialized
|
|
||||||
using a [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) primitive instance. The legacy classes can still be found
|
|
||||||
in `qiskit.algorithms.evolvers`.
|
|
||||||
|
|
||||||
In addition to the migration, the module has been substantially expanded to include Variational Quantum Time Evolution
|
|
||||||
(`qiskit.algorithms.time_evolvers.VarQTE`) solvers.
|
|
||||||
|
|
||||||
### TrotterQRTE
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
For the `TrotterQRTE` class, depending on the import path,
|
|
||||||
you will access either the primitive-based or the QuantumInstance-based
|
|
||||||
implementation. You have to be careful because the class name did not change.
|
|
||||||
|
|
||||||
- Old import path (QuantumInstance): `from qiskit.algorithms import TrotterQRTE`
|
|
||||||
- New import path (Primitives): `from qiskit.algorithms.time_evolvers import TrotterQRTE`
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
In addition to taking in a [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) instance instead of a [`qiskit.utils.QuantumInstance`](../qiskit/qiskit.utils.QuantumInstance),
|
|
||||||
the new [`qiskit.algorithms.eigensolvers.VQD`](../qiskit/0.44/qiskit.algorithms.eigensolvers.VQD) signature has undergone the following changes:
|
|
||||||
|
|
||||||
- The `expectation` parameter has been removed, as this functionality is now
|
|
||||||
defined at the `Estimator` level.
|
|
||||||
- The `num_timesteps` parameter has been added so you can define how many steps to divide the full evolution time in to.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
#### TrotterQRTE Example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import EvolutionProblem, TrotterQRTE
|
|
||||||
from qiskit.circuit import QuantumCircuit
|
|
||||||
from qiskit.opflow import PauliSumOp, AerPauliExpectation
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
|
|
||||||
operator = PauliSumOp.from_list([("X", 1),("Z", 1)])
|
|
||||||
initial_state = QuantumCircuit(1) # zero
|
|
||||||
time = 1
|
|
||||||
evolution_problem = EvolutionProblem(operator, 1, initial_state)
|
|
||||||
|
|
||||||
# Aer simulator using custom instruction
|
|
||||||
backend = AerSimulator()
|
|
||||||
quantum_instance = QuantumInstance(backend=backend)
|
|
||||||
expectation = AerPauliExpectation()
|
|
||||||
|
|
||||||
# LieTrotter with 1 rep
|
|
||||||
trotter_qrte = TrotterQRTE(expectation=expectation, quantum_instance=quantum_instance)
|
|
||||||
evolved_state = trotter_qrte.evolve(evolution_problem).evolved_state
|
|
||||||
|
|
||||||
print(evolved_state)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
CircuitStateFn(
|
|
||||||
┌─────────────────────┐
|
|
||||||
q: ┤ exp(-it (X + Z))(1) ├
|
|
||||||
└─────────────────────┘
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms.time_evolvers import TimeEvolutionProblem, TrotterQRTE # note new import!!!
|
|
||||||
from qiskit.circuit import QuantumCircuit
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit_aer.primitives import Estimator as AerEstimator
|
|
||||||
|
|
||||||
operator = SparsePauliOp.from_list([("X", 1),("Z", 1)])
|
|
||||||
initial_state = QuantumCircuit(1) # zero
|
|
||||||
time = 1
|
|
||||||
evolution_problem = TimeEvolutionProblem(operator, 1, initial_state)
|
|
||||||
|
|
||||||
# Aer simulator using custom instruction
|
|
||||||
estimator = AerEstimator(run_options={"approximation": True, "shots": None})
|
|
||||||
|
|
||||||
# LieTrotter with 1 rep
|
|
||||||
trotter_qrte = TrotterQRTE(estimator=estimator)
|
|
||||||
evolved_state = trotter_qrte.evolve(evolution_problem).evolved_state
|
|
||||||
|
|
||||||
print(evolved_state.decompose())
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
┌───────────┐┌───────────┐
|
|
||||||
q: ┤ exp(it X) ├┤ exp(it Z) ├
|
|
||||||
└───────────┘└───────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="amplitude"></span>
|
|
||||||
## Amplitude amplifiers
|
|
||||||
|
|
||||||
The amplitude amplifier algorithms were refactored in-place.
|
|
||||||
Instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), `qiskit.algorithms.amplitude_amplifiers` are now initialized
|
|
||||||
using an instance of any `Sampler` primitive. That is, [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The full `qiskit.algorithms.amplitude_amplifiers` module has been refactored in place. Therefore, you don't need to
|
|
||||||
change import paths.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Grover example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from qiskit.algorithms import Grover
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
|
|
||||||
qi = QuantumInstance(backend=backend)
|
|
||||||
grover = Grover(quantum_instance=qi)
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import Grover
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
grover = Grover(sampler=Sampler())
|
|
||||||
```
|
|
||||||
|
|
||||||
For complete code examples, see the following updated tutorials:
|
|
||||||
|
|
||||||
- [Amplitude Amplification and Grover](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/06_grover.ipynb)
|
|
||||||
- [Grover Examples](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/07_grover_examples.ipynb)
|
|
||||||
|
|
||||||
<span id="amp-estimate"></span>
|
|
||||||
## Amplitude estimators
|
|
||||||
|
|
||||||
Similarly to the amplitude amplifiers, the amplitude estimators were refactored in-place.
|
|
||||||
Instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), `qiskit.algorithms.amplitude_estimators` are now initialized
|
|
||||||
using an instance of any `Sampler` primitive. That is, [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The full `qiskit.algorithms.amplitude_estimators` module has been refactored in place. You do not need to
|
|
||||||
change import paths.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### IAE example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import IterativeAmplitudeEstimation
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
|
|
||||||
qi = QuantumInstance(backend=backend)
|
|
||||||
iae = IterativeAmplitudeEstimation(
|
|
||||||
epsilon_target=0.01, # target accuracy
|
|
||||||
alpha=0.05, # width of the confidence interval
|
|
||||||
quantum_instance=qi
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import IterativeAmplitudeEstimation
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
iae = IterativeAmplitudeEstimation(
|
|
||||||
epsilon_target=0.01, # target accuracy
|
|
||||||
alpha=0.05, # width of the confidence interval
|
|
||||||
sampler=Sampler()
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
For a complete code example, see the updated [Amplitude Estimation tutorial.](https://qiskit.org/ecosystem/finance/tutorials/00_amplitude_estimation.html)
|
|
||||||
|
|
||||||
<span id="phase"></span>
|
|
||||||
## Phase estimators
|
|
||||||
|
|
||||||
The phase estimators were refactored in-place.
|
|
||||||
Instead of a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), `qiskit.algorithms.phase_estimators` are now initialized by
|
|
||||||
using an instance of any `Sampler` primitive. That is, [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The full `qiskit.algorithms.phase_estimators` module has been refactored in place. Therefore, you do not need to change import paths.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### IPE example
|
|
||||||
|
|
||||||
**[Legacy] Using QuantumInstance:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import IterativePhaseEstimation
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
|
|
||||||
qi = QuantumInstance(backend=backend)
|
|
||||||
ipe = IterativePhaseEstimation(
|
|
||||||
num_iterations=num_iter,
|
|
||||||
quantum_instance=qi
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**[Updated] Using primitives:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.algorithms import IterativePhaseEstimation
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
ipe = IterativePhaseEstimation(
|
|
||||||
num_iterations=num_iter,
|
|
||||||
sampler=Sampler()
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
For a complete code examples, see the updated [Iterative phase estimation tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/09_IQPE.ipynb)
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,589 +0,0 @@
|
||||||
---
|
|
||||||
title: QuantumInstance migration guide
|
|
||||||
description: Stop using the deprecated Qiskit `QuantumInstance` class
|
|
||||||
---
|
|
||||||
|
|
||||||
# QuantumInstance migration guide
|
|
||||||
|
|
||||||
The [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) is a utility class that allows the joint
|
|
||||||
configuration of the circuit transpilation and execution steps, and provides functions
|
|
||||||
at a higher level of abstraction for a more convenient integration with algorithms.
|
|
||||||
These include measurement error mitigation, splitting and combining execution to
|
|
||||||
conform to job limits,
|
|
||||||
and ensuring reliable circuit execution with additional job management tools.
|
|
||||||
|
|
||||||
The [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) class is being deprecated for several reasons:
|
|
||||||
|
|
||||||
- The functionality of [`qiskit.utils.QuantumInstance.execute`](../qiskit/0.44/qiskit.utils.QuantumInstance#execute) has been delegated to the different implementations of the [`qiskit.primitives`](../qiskit/primitives) base classes.
|
|
||||||
- With the direct implementation of transpilation at the primitives level, the algorithms no longer need to manage that aspect of execution, and thus [`qiskit.utils.QuantumInstance.transpile`](../qiskit/0.44/qiskit.utils.QuantumInstance#transpile) is no longer required by the workflow. If desired, custom transpilation routines can still be performed at the user level through the [`qiskit.transpiler`](../qiskit/transpiler) module (see the table below).
|
|
||||||
|
|
||||||
The following table summarizes the migration alternatives for the [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) class:
|
|
||||||
|
|
||||||
| QuantumInstance method | Alternative |
|
|
||||||
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
||||||
| [`qiskit.utils.QuantumInstance.execute`](../qiskit/0.44/qiskit.utils.QuantumInstance#execute) | [`qiskit.primitives.Sampler.run`](../qiskit/qiskit.primitives.Sampler#run) or [`qiskit.primitives.Estimator.run`](../qiskit/qiskit.primitives.Estimator#run) |
|
|
||||||
| [`qiskit.utils.QuantumInstance.transpile`](../qiskit/0.44/qiskit.utils.QuantumInstance#transpile) | [`qiskit.compiler.transpile`](../qiskit/compiler#qiskit.compiler.transpile) |
|
|
||||||
| [`qiskit.utils.QuantumInstance.assemble`](../qiskit/0.44/qiskit.utils.QuantumInstance#assemble) | [`qiskit.compiler.assemble`](../qiskit/compiler#qiskit.compiler.assemble) |
|
|
||||||
|
|
||||||
The remainder of this guide focused on the [`qiskit.utils.QuantumInstance.execute`](../qiskit/0.44/qiskit.utils.QuantumInstance#execute) to
|
|
||||||
[`qiskit.primitives`](../qiskit/primitives) migration path.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
**Background on the Qiskit primitives**
|
|
||||||
|
|
||||||
The Qiskit primitives are algorithmic abstractions that encapsulate system or simulator access for easy integration into algorithm workflows.
|
|
||||||
|
|
||||||
There are two types of primitives: Sampler and Estimator.
|
|
||||||
|
|
||||||
Qiskit provides reference implementations in [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler) and [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator). Additionally,
|
|
||||||
[`qiskit.primitives.BackendSampler`](../qiskit/qiskit.primitives.BackendSampler) and [`qiskit.primitives.BackendEstimator`](../qiskit/qiskit.primitives.BackendEstimator) are
|
|
||||||
wrappers for `backend.run()` that follow the primitives interface.
|
|
||||||
|
|
||||||
Providers can implement these primitives as subclasses of [`qiskit.primitives.BaseSampler`](../qiskit/qiskit.primitives.BaseSampler) and [`qiskit.primitives.BaseEstimator`](../qiskit/qiskit.primitives.BaseEstimator), respectively.
|
|
||||||
IBM Qiskit Runtime ([`qiskit_ibm_runtime`](../qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService)) and Aer ([`qiskit_aer.primitives`](https://qiskit.org/ecosystem/aer/apidocs/aer_primitives.html)) are examples of native implementations of primitives.
|
|
||||||
|
|
||||||
This guide uses the following naming convention:
|
|
||||||
|
|
||||||
- _Primitives_ - Any Sampler or Estimator implementation using base classes [`qiskit.primitives.BackendSampler`](../qiskit/qiskit.primitives.BackendSampler) and a [`qiskit.primitives.BackendEstimator`](../qiskit/qiskit.primitives.BackendEstimator).
|
|
||||||
- _Reference primitives_ - [`qiskit.primitives.Sampler`](../qiskit/qiskit.primitives.Sampler) and [`qiskit.primitives.Estimator`](../qiskit/qiskit.primitives.Estimator) are reference implementations that come with Qiskit.
|
|
||||||
- _Aer primitives_ - The [Aer](https://qiskit.org/ecosystem/aer) primitive implementations [`qiskit_aer.primitives.Sampler`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Sampler.html) and [`qiskit_aer.primitives.Estimator`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Estimator.html).
|
|
||||||
- _Qiskit Runtime primitives_ - The IBM Qiskit Runtime primitive implementations [`qiskit_ibm_runtime.Sampler`](../qiskit-ibm-runtime/qiskit_ibm_runtime.Sampler) and [`qiskit_ibm_runtime.Estimator`](../qiskit-ibm-runtime/qiskit_ibm_runtime.Estimator).
|
|
||||||
- _`Backend` primitives_ - Instances of [`qiskit.primitives.BackendSampler`](../qiskit/qiskit.primitives.BackendSampler) and [`qiskit.primitives.BackendEstimator`](../qiskit/qiskit.primitives.BackendEstimator). These allow any system to implement primitive interfaces.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Choose the right primitive for your task
|
|
||||||
|
|
||||||
The [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) was designed to be an abstraction of transpile and run.
|
|
||||||
It took inspiration from [`qiskit.execute_function.execute`](../qiskit/execute#qiskit.execute_function.execute) but retained configuration information that could be set
|
|
||||||
at the algorithm level to save the user from defining the same parameters for every transpile or execute call.
|
|
||||||
|
|
||||||
The [`qiskit.primitives`](../qiskit/primitives) classes share some of these features, but unlike the [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance),
|
|
||||||
there are multiple primitive classes, and each is optimized for a specific
|
|
||||||
purpose. Selecting the right primitive (`Sampler` or `Estimator`) requires some knowledge about
|
|
||||||
**what** it is expected to do and **where** or **how** it is expected to run.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Primitives are also **algorithmic** abstractions with defined tasks:
|
|
||||||
|
|
||||||
- The `Estimator` takes in circuits and observables and returns **expectation values**.
|
|
||||||
- The `Sampler` takes in circuits, measures them, and returns their **quasi-probability distributions**.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
To determine which primitive to use instead of [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), you should ask
|
|
||||||
yourself two questions:
|
|
||||||
|
|
||||||
1. What is the minimal unit of information used by your algorithm?
|
|
||||||
- If it uses an expectation value, you need an `Estimator`.
|
|
||||||
- If it uses a probability distribution (from sampleing the devicd), you need a `Sampler`
|
|
||||||
|
|
||||||
2. How do you want to run your circuits?
|
|
||||||
|
|
||||||
This question is not new. In the legacy algorithm workflow, you would set up a
|
|
||||||
[`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) with either a real system from a provider, or a simulator.
|
|
||||||
For this migration, this "system selection" process is translated to **where** do you import your primitives from:
|
|
||||||
|
|
||||||
- Using **local** statevector simulators for quick prototyping: **Reference primitives**
|
|
||||||
- Using **local** noisy simulations for finer algorithm tuning: **Aer primitives**
|
|
||||||
- Accessing **runtime-enabled systems** (or cloud simulators): **Qiskit Runtime primitives**
|
|
||||||
- Accessing **non runtime-enabled systems** : **`Backend` primitives**
|
|
||||||
|
|
||||||
Arguably, the `Sampler` is the closest primitive to [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance), as they
|
|
||||||
both execute circuits and provide a result. However, with the [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance),
|
|
||||||
the result data was system-dependent (it could be a counts `dict`, a `numpy.array` for
|
|
||||||
statevector simulations, and so on), while `Sampler` normalizes its `SamplerResult` to
|
|
||||||
return a [`qiskit.result.QuasiDistribution`](../qiskit/qiskit.result.QuasiDistribution) object with the resulting quasi-probability distribution.
|
|
||||||
|
|
||||||
The `Estimator` provides a specific abstraction for the expectation value calculation that can replace
|
|
||||||
[`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) as well as the associated pre- and post-processing steps, usually performed
|
|
||||||
with an additional library such as [`qiskit.opflow`](../qiskit/0.44/opflow).
|
|
||||||
|
|
||||||
## Choose the right primitive for your settings
|
|
||||||
|
|
||||||
Certain [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) features are only available in certain primitive implementations.
|
|
||||||
The following table summarizes the most common [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance) settings and which
|
|
||||||
primitives expose a similar setting through their interface:
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
In some cases, a setting might not be exposed through the interface, but there might be an alternative path to make
|
|
||||||
it work. This is the case for custom transpiler passes, which cannot be set through the primitives interface,
|
|
||||||
but pre-transpiled circuits can be sent if you specify the option `skip_transpilation=True`. For more information,
|
|
||||||
refer to the API reference or source code of the desired primitive implementation.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
| QuantumInstance | Reference Primitives | Aer Primitives | Qiskit Runtime Primitives | `Backend` Primitives |
|
|
||||||
| ----------------------------------------------------------------------------------------------------- | -------------------- | -------------- | --------------------------------- | ------------------------------------- |
|
|
||||||
| Select `backend` | No | No | Yes | Yes |
|
|
||||||
| Set `shots` | Yes | Yes | Yes | Yes |
|
|
||||||
| Simulator settings: `basis_gates`, `coupling_map`, `initial_layout`, `noise_model`, `backend_options` | No | Yes | Yes | No (inferred from internal `backend`) |
|
|
||||||
| Transpiler settings: `seed_transpiler`, `optimization_level` | No | No | Yes (via `options`) (\*) | Yes (via `.set_transpile_options()`) |
|
|
||||||
| Set unbound `pass_manager` | No | No | No (but can `skip_transpilation`) | No (but can `skip_transpilation`) |
|
|
||||||
| Set `bound_pass_manager` | No | No | No | Yes |
|
|
||||||
| Set `backend_options`: common ones were `memory` and `meas_level` | No | No | No (only `qubit_layout`) | No |
|
|
||||||
| Measurement error mitigation: `measurement_error_mitigation_cls`, `cals_matrix_refresh_period`, | No | No | Sampler default > M3 (\*) | No |
|
|
||||||
| Job management: `job_callback`, `max_job_retries`, `timeout`, `wait` | Does not apply | Does not apply | Sessions, callback (\*\*) | No |
|
|
||||||
|
|
||||||
(\*) For more information on error mitigation and setting options on Qiskit Runtime Primitives, see
|
|
||||||
[Advanced Runtime Options](../../run/advanced-runtime-options).
|
|
||||||
|
|
||||||
(\*\*) For more information on Runtime sessions, see [About Sessions](../../run/sessions).
|
|
||||||
|
|
||||||
## Code examples
|
|
||||||
|
|
||||||
### Example 1: Circuit sampling with local simulation
|
|
||||||
|
|
||||||
**QuantumInstance**
|
|
||||||
|
|
||||||
The only option for local simulations using the quantum instance was using an Aer simulator.
|
|
||||||
If no simulation method is specified, the Aer simulator defaults to an exact simulation
|
|
||||||
(statevector/stabilizer), if shots are specified, it adds shot noise.
|
|
||||||
Note that `QuantumInstance.execute()` returned the counts in hexadecimal format.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2)
|
|
||||||
circuit.x(0)
|
|
||||||
circuit.x(1)
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
simulator = AerSimulator()
|
|
||||||
qi = QuantumInstance(backend=simulator, shots=200)
|
|
||||||
result = qi.execute(circuit).results[0]
|
|
||||||
data = result.data
|
|
||||||
counts = data.counts
|
|
||||||
|
|
||||||
print("Counts: ", counts)
|
|
||||||
print("Data: ", data)
|
|
||||||
print("Result: ", result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
Counts: {'0x3': 200}
|
|
||||||
Data: ExperimentResultData(counts={'0x3': 200})
|
|
||||||
Result: ExperimentResult(shots=200, success=True, meas_level=2, data=ExperimentResultData(counts={'0x3': 200}), header=QobjExperimentHeader(clbit_labels=[['meas', 0], ['meas', 1]], creg_sizes=[['meas', 2]], global_phase=0.0, memory_slots=2, metadata={}, n_qubits=2, name='circuit-99', qreg_sizes=[['q', 2]], qubit_labels=[['q', 0], ['q', 1]]), status=DONE, seed_simulator=2846213898, metadata={'parallel_state_update': 16, 'parallel_shots': 1, 'sample_measure_time': 0.00025145, 'noise': 'ideal', 'batched_shots_optimization': False, 'remapped_qubits': False, 'device': 'CPU', 'active_input_qubits': [0, 1], 'measure_sampling': True, 'num_clbits': 2, 'input_qubit_map': [[1, 1], [0, 0]], 'num_qubits': 2, 'method': 'stabilizer', 'fusion': {'enabled': False}}, time_taken=0.000672166)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Primitives**
|
|
||||||
|
|
||||||
The primitives offer two alternatives for local simulation, one with the Reference primitives
|
|
||||||
and one with the Aer primitives. As mentioned above, the closest alternative to `QuantumInstance.execute()`
|
|
||||||
for sampling is the Sampler primitive.
|
|
||||||
|
|
||||||
**a. Reference primitives**
|
|
||||||
|
|
||||||
Basic simulation implemented using the [`qiskit.quantum_info`](../qiskit/quantum_info) module. If shots are
|
|
||||||
specified, the results include shot noise. Note that
|
|
||||||
the resulting quasi-probability distribution does not use bitstrings, but integers to identify the states.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2)
|
|
||||||
circuit.x(0)
|
|
||||||
circuit.x(1)
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
sampler = Sampler()
|
|
||||||
result = sampler.run(circuit, shots=200).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
|
|
||||||
print("Quasi-dists: ", quasi_dists)
|
|
||||||
print("Result: ", result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
Quasi-dists: [{3: 1.0}]
|
|
||||||
Result: SamplerResult(quasi_dists=[{3: 1.0}], metadata=[{'shots': 200}])
|
|
||||||
```
|
|
||||||
|
|
||||||
**b. Aer primitives**
|
|
||||||
|
|
||||||
This method uses Aer simulation following the statevector method. This is a closer replacement of the
|
|
||||||
[`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance)
|
|
||||||
example, as they are access the same simulator. Note that
|
|
||||||
the resulting quasi-probability distribution does not use bitstrings but integers to identify the states.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The [`qiskit.result.QuasiDistribution`](../qiskit/qiskit.result.QuasiDistribution) class that is returned as part of the [`qiskit.primitives.SamplerResult`](../qiskit/qiskit.primitives.SamplerResult)
|
|
||||||
exposes two methods to convert the result keys from integer to binary strings / hexadecimal:
|
|
||||||
|
|
||||||
```
|
|
||||||
- [`qiskit.result.QuasiDistribution.binary_probabilities`](../qiskit/qiskit.result.QuasiDistribution#binary_probabilities)
|
|
||||||
- [`qiskit.result.QuasiDistribution.hex_probabilities`](../qiskit/qiskit.result.QuasiDistribution#hex_probabilities)
|
|
||||||
```
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit_aer.primitives import Sampler
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2)
|
|
||||||
circuit.x(0)
|
|
||||||
circuit.x(1)
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
# If a noise model is provided, the Aer primitives
|
|
||||||
# perform an exact (statevector) simulation
|
|
||||||
sampler = Sampler()
|
|
||||||
result = sampler.run(circuit, shots=200).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
# convert keys to binary bitstrings
|
|
||||||
binary_dist = quasi_dists[0].binary_probabilities()
|
|
||||||
|
|
||||||
print("Quasi-dists: ", quasi_dists)
|
|
||||||
print("Result: ", result)
|
|
||||||
print("Binary quasi-dist: ", binary_dist)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
Quasi-dists: [{3: 1.0}]
|
|
||||||
Result: SamplerResult(quasi_dists=[{3: 1.0}], metadata=[{'shots': 200, 'simulator_metadata': {'parallel_state_update': 16, 'parallel_shots': 1, 'sample_measure_time': 9.016e-05, 'noise': 'ideal', 'batched_shots_optimization': False, 'remapped_qubits': False, 'device': 'CPU', 'active_input_qubits': [0, 1], 'measure_sampling': True, 'num_clbits': 2, 'input_qubit_map': [[1, 1], [0, 0]], 'num_qubits': 2, 'method': 'statevector', 'fusion': {'applied': False, 'max_fused_qubits': 5, 'threshold': 14, 'enabled': True}}}])
|
|
||||||
Binary quasi-dist: {'11': 1.0}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 2: Expectation value calculation with local noisy simulation
|
|
||||||
|
|
||||||
While this example does not include a direct call to `QuantumInstance.execute()`, it shows
|
|
||||||
how to migrate from a [`qiskit.utils.QuantumInstance`](../qiskit/0.44/qiskit.utils.QuantumInstance)-based to a [`qiskit.primitives`](../qiskit/primitives)-based
|
|
||||||
workflow.
|
|
||||||
|
|
||||||
**QuantumInstance**
|
|
||||||
|
|
||||||
The most common use case for computing expectation values with the Quantum Instance was as in combination with the
|
|
||||||
[`qiskit.opflow`](../qiskit/0.44/opflow) library. You can see more information in the [opflow migration guide](./qiskit-opflow-module).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.opflow import StateFn, PauliSumOp, PauliExpectation, CircuitSampler
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
from qiskit_aer.noise import NoiseModel
|
|
||||||
from qiskit_ibm_provider import IBMProvider
|
|
||||||
|
|
||||||
# Define problem using opflow
|
|
||||||
op = PauliSumOp.from_list([("XY",1)])
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.x(0)
|
|
||||||
qc.x(1)
|
|
||||||
|
|
||||||
state = StateFn(qc)
|
|
||||||
measurable_expression = StateFn(op, is_measurement=True).compose(state)
|
|
||||||
expectation = PauliExpectation().convert(measurable_expression)
|
|
||||||
|
|
||||||
# Define QuantumInstance with a noisy simulator
|
|
||||||
provider = IBMProvider()
|
|
||||||
device = provider.get_backend("ibmq_manila")
|
|
||||||
noise_model = NoiseModel.from_backend(device)
|
|
||||||
coupling_map = device.configuration().coupling_map
|
|
||||||
|
|
||||||
backend = AerSimulator()
|
|
||||||
qi = QuantumInstance(backend=backend, shots=1024,
|
|
||||||
seed_simulator=42, seed_transpiler=42,
|
|
||||||
coupling_map=coupling_map, noise_model=noise_model)
|
|
||||||
|
|
||||||
# Run
|
|
||||||
sampler = CircuitSampler(qi).convert(expectation)
|
|
||||||
expectation_value = sampler.eval().real
|
|
||||||
|
|
||||||
print(expectation_value)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
-0.04687500000000008
|
|
||||||
```
|
|
||||||
|
|
||||||
**Primitives**
|
|
||||||
|
|
||||||
The primitives allow the combination of the opflow and QuantumInstance functionality in a single `Estimator`.
|
|
||||||
In this case, for local noisy simulation, this will be the Aer estimator.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit_aer.noise import NoiseModel
|
|
||||||
from qiskit_aer.primitives import Estimator
|
|
||||||
from qiskit_ibm_provider import IBMProvider
|
|
||||||
|
|
||||||
# Define problem
|
|
||||||
op = SparsePauliOp("XY")
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.x(0)
|
|
||||||
qc.x(1)
|
|
||||||
|
|
||||||
# Define Aer Estimator with noisy simulator
|
|
||||||
device = provider.get_backend("ibmq_manila")
|
|
||||||
noise_model = NoiseModel.from_backend(device)
|
|
||||||
coupling_map = device.configuration().coupling_map
|
|
||||||
|
|
||||||
# If a noise model is provided, the Aer primitives
|
|
||||||
# perform a "qasm" simulation
|
|
||||||
estimator = Estimator(
|
|
||||||
backend_options={ # method chosen automatically to match options
|
|
||||||
"coupling_map": coupling_map,
|
|
||||||
"noise_model": noise_model,
|
|
||||||
},
|
|
||||||
run_options={"seed": 42, "shots": 1024},
|
|
||||||
transpile_options={"seed_transpiler": 42},
|
|
||||||
)
|
|
||||||
|
|
||||||
# Run
|
|
||||||
expectation_value = estimator.run(qc, op).result().values
|
|
||||||
|
|
||||||
print(expectation_value)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
[-0.04101562]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 3: Circuit sampling on IBM system with error mitigation
|
|
||||||
|
|
||||||
**QuantumInstance**
|
|
||||||
|
|
||||||
The `QuantumInstance` interface allowed configuring measurement error mitigation settings such as the method, the
|
|
||||||
matrix refresh period, or the mitigation pattern. This configuration is no longer available in the primitives
|
|
||||||
interface.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
from qiskit.utils.mitigation import CompleteMeasFitter
|
|
||||||
from qiskit_ibm_provider import IBMProvider
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2)
|
|
||||||
circuit.x(0)
|
|
||||||
circuit.x(1)
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
provider = IBMProvider()
|
|
||||||
backend = provider.get_backend("ibmq_montreal")
|
|
||||||
|
|
||||||
qi = QuantumInstance(
|
|
||||||
backend=backend,
|
|
||||||
shots=4000,
|
|
||||||
measurement_error_mitigation_cls=CompleteMeasFitter,
|
|
||||||
cals_matrix_refresh_period=0,
|
|
||||||
)
|
|
||||||
|
|
||||||
result = qi.execute(circuit).results[0].data
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
ExperimentResultData(counts={'11': 4000})
|
|
||||||
```
|
|
||||||
|
|
||||||
**Primitives**
|
|
||||||
|
|
||||||
The Qiskit Runtime primitives offer a suite of error mitigation methods that can be easily turned on with the
|
|
||||||
`resilience_level` option. These are, however, not configurable. The sampler's `resilience_level=1`
|
|
||||||
is the closest alternative to the QuantumInstance measurement error mitigation implementation, but this
|
|
||||||
is not a one-to-one replacement.
|
|
||||||
|
|
||||||
For more information about the error mitigation options in the Qiskit Runtime primitives, see [Configure Error Mitigation](../../run/configure-error-mitigation).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2)
|
|
||||||
circuit.x(0)
|
|
||||||
circuit.x(1)
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum")
|
|
||||||
backend = service.backend("ibmq_montreal")
|
|
||||||
|
|
||||||
options = Options(resilience_level = 1) # 1 = measurement error mitigation
|
|
||||||
sampler = Sampler(session=backend, options=options)
|
|
||||||
|
|
||||||
# Run
|
|
||||||
result = sampler.run(circuit, shots=4000).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
|
|
||||||
print("Quasi dists: ", quasi_dists)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
Quasi dists: [{2: 0.0008492371522941081, 3: 0.9968874384378738, 0: -0.0003921227905920063,
|
|
||||||
1: 0.002655447200424097}]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 4: Circuit sampling with custom bound and unbound pass managers
|
|
||||||
|
|
||||||
Transpilation management is different between `QuantumInstance` and the primitives.
|
|
||||||
|
|
||||||
QuantumInstance allowed you to:
|
|
||||||
|
|
||||||
- Define bound and unbound pass managers that were called during `.execute()`.
|
|
||||||
- Explicitly call its `.transpile()` method with a specific pass manager.
|
|
||||||
|
|
||||||
QuantumInstance **did not** manage parameter bindings on parametrized quantum circuits. Therefore, if a `bound_pass_manager` was set, the circuit sent to `QuantumInstance.execute()` could
|
|
||||||
not have any free parameters.
|
|
||||||
|
|
||||||
When using the primitives:
|
|
||||||
|
|
||||||
- You cannot explicitly access their transpilation routine.
|
|
||||||
- The mechanism to apply custom transpilation passes to the Aer, Runtime, and `Backend` primitives is to pre-transpile
|
|
||||||
locally and set `skip_transpilation=True` in the corresponding primitive.
|
|
||||||
- The only primitives that accept a custom **bound** transpiler pass manager are instances of [`qiskit.primitives.BackendSampler`](../qiskit/qiskit.primitives.BackendSampler) or [`qiskit.primitives.BackendEstimator`](../qiskit/qiskit.primitives.BackendEstimator).
|
|
||||||
If a `bound_pass_manager` is defined, the `skip_transpilation=True` option does **not** skip this bound pass.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
Care is needed when setting `skip_transpilation=True` with the Estimator primitive.
|
|
||||||
Since operator and circuit size need to match for the Estimator, if the custom transpilation changes
|
|
||||||
the circuit size, the operator must be adapted before sending it
|
|
||||||
to the Estimator, as there is no mechanism to identify the active qubits it should consider.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Note that the primitives do handle parameter bindings, so that even if a `bound_pass_manager` is defined in a
|
|
||||||
[`qiskit.primitives.BackendSampler`](../qiskit/qiskit.primitives.BackendSampler) or [`qiskit.primitives.BackendEstimator`](../qiskit/qiskit.primitives.BackendEstimator), you do not have to manually assign parameters as expected in the QuantumInstance workflow.
|
|
||||||
|
|
||||||
The two-stage transpilation was added to the `QuantumInstance` to allow running pulse-efficient transpilation passes with the [`qiskit.opflow.converters.CircuitSampler`](../qiskit/0.44/qiskit.opflow.converters.CircuitSampler) class. The following
|
|
||||||
example shows how to migrate this use case, where the `QuantumInstance.execute()` method is called by the [`qiskit.opflow.converters.CircuitSampler`](../qiskit/0.44/qiskit.opflow.converters.CircuitSampler) code.
|
|
||||||
|
|
||||||
**QuantumInstance**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit.library.standard_gates.equivalence_library import StandardEquivalenceLibrary as std_eqlib
|
|
||||||
from qiskit.circuit.library import RealAmplitudes
|
|
||||||
from qiskit.opflow import CircuitSampler, StateFn
|
|
||||||
from qiskit.providers.fake_provider import FakeBelem
|
|
||||||
from qiskit.transpiler import PassManager, PassManagerConfig, CouplingMap
|
|
||||||
from qiskit.transpiler.preset_passmanagers import level_1_pass_manager
|
|
||||||
from qiskit.transpiler.passes import (
|
|
||||||
Collect2qBlocks, ConsolidateBlocks, Optimize1qGatesDecomposition,
|
|
||||||
RZXCalibrationBuilderNoEcho, UnrollCustomDefinitions, BasisTranslator
|
|
||||||
)
|
|
||||||
from qiskit.transpiler.passes.optimization.echo_rzx_weyl_decomposition import EchoRZXWeylDecomposition
|
|
||||||
from qiskit.utils import QuantumInstance
|
|
||||||
|
|
||||||
# Define backend
|
|
||||||
backend = FakeBelem()
|
|
||||||
|
|
||||||
# Build the pass manager for the parameterized circuit
|
|
||||||
rzx_basis = ['rzx', 'rz', 'x', 'sx']
|
|
||||||
coupling_map = CouplingMap(backend.configuration().coupling_map)
|
|
||||||
config = PassManagerConfig(basis_gates=rzx_basis, coupling_map=coupling_map)
|
|
||||||
pre = level_1_pass_manager(config)
|
|
||||||
inst_map = backend.defaults().instruction_schedule_map
|
|
||||||
|
|
||||||
# Build a pass manager for the CX decomposition (works only on bound circuits)
|
|
||||||
post = PassManager([
|
|
||||||
# Consolidate consecutive two-qubit operations.
|
|
||||||
Collect2qBlocks(),
|
|
||||||
ConsolidateBlocks(basis_gates=['rz', 'sx', 'x', 'rxx']),
|
|
||||||
|
|
||||||
# Rewrite circuit in terms of Weyl-decomposed echoed RZX gates.
|
|
||||||
EchoRZXWeylDecomposition(inst_map),
|
|
||||||
|
|
||||||
# Attach scaled CR pulse schedules to the RZX gates.
|
|
||||||
RZXCalibrationBuilderNoEcho(inst_map),
|
|
||||||
|
|
||||||
# Simplify single-qubit gates.
|
|
||||||
UnrollCustomDefinitions(std_eqlib, rzx_basis),
|
|
||||||
BasisTranslator(std_eqlib, rzx_basis),
|
|
||||||
Optimize1qGatesDecomposition(rzx_basis),
|
|
||||||
])
|
|
||||||
|
|
||||||
# Instantiate qi
|
|
||||||
quantum_instance = QuantumInstance(backend, pass_manager=pre, bound_pass_manager=post)
|
|
||||||
|
|
||||||
# Define parametrized circuit and parameter values
|
|
||||||
qc = RealAmplitudes(2)
|
|
||||||
print(qc.decompose())
|
|
||||||
param_dict = {p: 0.5 for p in qc.parameters}
|
|
||||||
|
|
||||||
# Instantiate CircuitSampler
|
|
||||||
sampler = CircuitSampler(quantum_instance)
|
|
||||||
|
|
||||||
# Run
|
|
||||||
quasi_dists = sampler.convert(StateFn(qc), params=param_dict).sample()
|
|
||||||
print("Quasi-dists: ", quasi_dists)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
||||||
q_0: ┤ Ry(θ[0]) ├──■──┤ Ry(θ[2]) ├──■──┤ Ry(θ[4]) ├──■──┤ Ry(θ[6]) ├
|
|
||||||
├──────────┤┌─┴─┐├──────────┤┌─┴─┐├──────────┤┌─┴─┐├──────────┤
|
|
||||||
q_1: ┤ Ry(θ[1]) ├┤ X ├┤ Ry(θ[3]) ├┤ X ├┤ Ry(θ[5]) ├┤ X ├┤ Ry(θ[7]) ├
|
|
||||||
└──────────┘└───┘└──────────┘└───┘└──────────┘└───┘└──────────┘
|
|
||||||
Quasi-dists: {'11': 0.443359375, '10': 0.21875, '01': 0.189453125, '00': 0.1484375}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Primitives**
|
|
||||||
|
|
||||||
Let's see how the workflow changes with the `Backend` Sampler:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit.library.standard_gates.equivalence_library import StandardEquivalenceLibrary as std_eqlib
|
|
||||||
from qiskit.circuit.library import RealAmplitudes
|
|
||||||
from qiskit.primitives import BackendSampler
|
|
||||||
from qiskit.providers.fake_provider import FakeBelem
|
|
||||||
from qiskit.transpiler import PassManager, PassManagerConfig, CouplingMap
|
|
||||||
from qiskit.transpiler.preset_passmanagers import level_1_pass_manager
|
|
||||||
from qiskit.transpiler.passes import (
|
|
||||||
Collect2qBlocks, ConsolidateBlocks, Optimize1qGatesDecomposition,
|
|
||||||
RZXCalibrationBuilderNoEcho, UnrollCustomDefinitions, BasisTranslator
|
|
||||||
)
|
|
||||||
from qiskit.transpiler.passes.optimization.echo_rzx_weyl_decomposition import EchoRZXWeylDecomposition
|
|
||||||
|
|
||||||
# Define backend
|
|
||||||
backend = FakeBelem()
|
|
||||||
|
|
||||||
# Build the pass manager for the parameterized circuit
|
|
||||||
rzx_basis = ['rzx', 'rz', 'x', 'sx']
|
|
||||||
coupling_map = CouplingMap(backend.configuration().coupling_map)
|
|
||||||
config = PassManagerConfig(basis_gates=rzx_basis, coupling_map=coupling_map)
|
|
||||||
pre = level_1_pass_manager(config)
|
|
||||||
|
|
||||||
# Build a pass manager for the CX decomposition (works only on bound circuits)
|
|
||||||
inst_map = backend.defaults().instruction_schedule_map
|
|
||||||
post = PassManager([
|
|
||||||
# Consolidate consecutive two-qubit operations.
|
|
||||||
Collect2qBlocks(),
|
|
||||||
ConsolidateBlocks(basis_gates=['rz', 'sx', 'x', 'rxx']),
|
|
||||||
|
|
||||||
# Rewrite circuit in terms of Weyl-decomposed echoed RZX gates.
|
|
||||||
EchoRZXWeylDecomposition(inst_map),
|
|
||||||
|
|
||||||
# Attach scaled CR pulse schedules to the RZX gates.
|
|
||||||
RZXCalibrationBuilderNoEcho(inst_map),
|
|
||||||
|
|
||||||
# Simplify single-qubit gates.
|
|
||||||
UnrollCustomDefinitions(std_eqlib, rzx_basis),
|
|
||||||
BasisTranslator(std_eqlib, rzx_basis),
|
|
||||||
Optimize1qGatesDecomposition(rzx_basis),
|
|
||||||
])
|
|
||||||
|
|
||||||
# Define parametrized circuit and parameter values
|
|
||||||
qc = RealAmplitudes(2)
|
|
||||||
qc.measure_all() # add measurements!
|
|
||||||
print(qc.decompose())
|
|
||||||
|
|
||||||
# Instantiate backend sampler with skip_transpilation
|
|
||||||
sampler = BackendSampler(backend=backend, skip_transpilation=True, bound_pass_manager=post)
|
|
||||||
|
|
||||||
# Run unbound transpiler pass
|
|
||||||
transpiled_circuit = pre.run(qc)
|
|
||||||
|
|
||||||
# Run sampler
|
|
||||||
quasi_dists = sampler.run(transpiled_circuit, [[0.5] * len(qc.parameters)]).result().quasi_dists
|
|
||||||
print("Quasi-dists: ", quasi_dists)
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ░ ┌─┐
|
|
||||||
q_0: ┤ Ry(θ[0]) ├──■──┤ Ry(θ[2]) ├──■──┤ Ry(θ[4]) ├──■──┤ Ry(θ[6]) ├─░─┤M├───
|
|
||||||
├──────────┤┌─┴─┐├──────────┤┌─┴─┐├──────────┤┌─┴─┐├──────────┤ ░ └╥┘┌─┐
|
|
||||||
q_1: ┤ Ry(θ[1]) ├┤ X ├┤ Ry(θ[3]) ├┤ X ├┤ Ry(θ[5]) ├┤ X ├┤ Ry(θ[7]) ├─░──╫─┤M├
|
|
||||||
└──────────┘└───┘└──────────┘└───┘└──────────┘└───┘└──────────┘ ░ ║ └╥┘
|
|
||||||
meas: 2/═══════════════════════════════════════════════════════════════════╩══╩═
|
|
||||||
0 1
|
|
||||||
Quasi-dists: [{1: 0.18359375, 2: 0.2333984375, 0: 0.1748046875, 3: 0.408203125}]
|
|
||||||
```
|
|
|
@ -1,674 +0,0 @@
|
||||||
---
|
|
||||||
title: Qiskit Runtime migration examples
|
|
||||||
description: Examples of migrating from using backend.run to using Qiskit Runtime primitives
|
|
||||||
---
|
|
||||||
|
|
||||||
# Migration examples
|
|
||||||
|
|
||||||
Follow these examples to design a Qiskit Runtime algorithm.
|
|
||||||
|
|
||||||
<span id="estimator-algorithm"></span>
|
|
||||||
## Use Estimator to design an algorithm
|
|
||||||
|
|
||||||
The Estimator primitive is used to design an algorithm that calculates
|
|
||||||
expectation values.
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
The role of the `Estimator` primitive is two-fold: it acts as an **entry point** to quantum devices or simulators, replacing the `Backend`
|
|
||||||
interface (commonly referred to as `backend.run()`). Additionally, it is
|
|
||||||
an **algorithmic abstraction** for expectation value calculations, so
|
|
||||||
you don't have to manually construct the final expectation circuit.
|
|
||||||
This results in a considerable reduction of the code complexity and a
|
|
||||||
more compact algorithm design.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
**Backend.run() model:** In this model, you accessed real systems and remote simulators using the `qiskit-ibmq-provider` module (now migrated to `qiskit-ibm-provider`). To run **local** simulations, you could import a specific simulator from `qiskit-aer`. All of them followed the `backend.run()` interface.
|
|
||||||
|
|
||||||
````
|
|
||||||
<details>
|
|
||||||
<summary>Code example for `qiskit-ibmq-provider` & `backend.run()`</summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit import IBMQ
|
|
||||||
|
|
||||||
# Select provider
|
|
||||||
provider = IBMQ.get_provider(hub="ibm-q", group="open", project="main")
|
|
||||||
|
|
||||||
# Get backend
|
|
||||||
backend = provider.get_backend("ibmq_qasm_simulator") # cloud simulator
|
|
||||||
|
|
||||||
# Run
|
|
||||||
result = backend.run(expectation_circuits)
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Code example for `qiskit-aer` & `backend.run()`</summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_aer import AerSimulator # former import: from qiskit import Aer
|
|
||||||
|
|
||||||
# Get local simulator backend
|
|
||||||
backend = AerSimulator()
|
|
||||||
|
|
||||||
# Run
|
|
||||||
result = backend.run(expectation_circuits)
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
**Primitives model:** Access real systems and remote simulators through the `qiskit-ibm-runtime` **primitives** (`Sampler` and `Estimator`). To run **local** simulations, you can import specific local primitives from `qiskit_aer.primitives` and `qiskit.primitives`. All of them follow the `BaseSampler` and `BaseEstimator` interfaces, but **only the Runtime primitives offer access to the Runtime service, sessions, and built-in error mitigation**.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Code example for Runtime Estimator</summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
|
|
||||||
|
|
||||||
# Define service
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
# Get backend
|
|
||||||
backend = service.backend("ibmq_qasm_simulator") # cloud simulator
|
|
||||||
|
|
||||||
# Define Estimator
|
|
||||||
# (see tutorials for more information about sessions)
|
|
||||||
estimator = Estimator(session=backend)
|
|
||||||
|
|
||||||
# Run Expectation value calculation
|
|
||||||
result = estimator.run(circuits, observables).result()
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Code example for Aer Estimator</summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_aer import Estimator
|
|
||||||
|
|
||||||
# Get local simulator Estimator
|
|
||||||
estimator = Estimator()
|
|
||||||
|
|
||||||
# Run expectation value calculation
|
|
||||||
result = estimator.run(circuits, observables).result()
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
````
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
If your code previously calculated expectation values using
|
|
||||||
`backend.run()`, you most likely used the `qiskit.opflow` module to
|
|
||||||
handle operators and state functions. To support this scenario, the
|
|
||||||
following migration example shows how to replace the (`qiskit.opflow` & `backend.run()`) workflow with an Estimator-based workflow.
|
|
||||||
|
|
||||||
### End-to-end example
|
|
||||||
|
|
||||||
#### 1. Problem definition
|
|
||||||
|
|
||||||
We want to compute the expectation value of a quantum state (circuit)
|
|
||||||
with respect to a certain operator. In this example, we are using the H2
|
|
||||||
molecule and an arbitrary circuit as the quantum state:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
# Step 1: Define operator
|
|
||||||
op = SparsePauliOp.from_list(
|
|
||||||
[
|
|
||||||
("II", -1.052373245772859),
|
|
||||||
("IZ", 0.39793742484318045),
|
|
||||||
("ZI", -0.39793742484318045),
|
|
||||||
("ZZ", -0.01128010425623538),
|
|
||||||
("XX", 0.18093119978423156),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Step 2: Define quantum state
|
|
||||||
state = QuantumCircuit(2)
|
|
||||||
state.x(0)
|
|
||||||
state.x(1)
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="legacy-opflow"></span>
|
|
||||||
##### 1.a. Legacy: Convert problem to opflow
|
|
||||||
|
|
||||||
`qiskit.opflow` provided its own classes to represent both operators
|
|
||||||
and quantum states, so the problem defined above would be wrapped as:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.opflow import CircuitStateFn, PauliSumOp
|
|
||||||
|
|
||||||
opflow_op = PauliSumOp(op)
|
|
||||||
opflow_state = CircuitStateFn(state)
|
|
||||||
```
|
|
||||||
|
|
||||||
This step is no longer necessary when using the primitives.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
For instructions to migrate from `qiskit.opflow`, see the [Opflow migration guide](./qiskit-opflow-module).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
#### 2. Calculate expectation values on real device or cloud simulator
|
|
||||||
|
|
||||||
##### 2.a. Legacy: Use opflow & backend.run()
|
|
||||||
|
|
||||||
The legacy workflow required many steps to compute an expectation value:
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Replace `ibmq_qasm_simulator` with your device name to see the complete workflow for a real device.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.opflow import StateFn, PauliExpectation, CircuitSampler
|
|
||||||
from qiskit import IBMQ
|
|
||||||
|
|
||||||
# Define the state to sample
|
|
||||||
measurable_expression = StateFn(opflow_op, is_measurement=True).compose(opflow_state)
|
|
||||||
|
|
||||||
# Convert to expectation value calculation object
|
|
||||||
expectation = PauliExpectation().convert(measurable_expression)
|
|
||||||
|
|
||||||
# Define provider and backend
|
|
||||||
provider = IBMQ.get_provider(hub="ibm-q", group="open", project="main")
|
|
||||||
backend = provider.get_backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
# Inject backend into circuit sampler
|
|
||||||
sampler = CircuitSampler(backend).convert(expectation)
|
|
||||||
|
|
||||||
# Evaluate
|
|
||||||
expectation_value = sampler.eval().real
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("expectation: ", expectation_value)
|
|
||||||
expectation: -1.065734058826613
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 2.b. Updated: Use the Estimator Runtime primitive
|
|
||||||
|
|
||||||
The `Estimator` simplifies the user-side syntax, making it a more
|
|
||||||
convenient tool for algorithm design.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Replace `ibmq_qasm_simulator` with your device name to see the complete workflow for a real device.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
estimator = Estimator(session=backend)
|
|
||||||
|
|
||||||
expectation_value = estimator.run(state, op).result().values
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the Estimator returns a list of values, as it can perform batched evaluations.
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("expectation: ", expectation_value)
|
|
||||||
expectation: [-1.06329149]
|
|
||||||
```
|
|
||||||
|
|
||||||
The `Estimator` Runtime primitive offers a series of features and tuning
|
|
||||||
options that do not have a legacy alternative to migrate from, but can
|
|
||||||
help improve your performance and results. For more information, refer
|
|
||||||
to the following:
|
|
||||||
|
|
||||||
- [Setting execution options
|
|
||||||
topic](../../run/advanced-runtime-options)
|
|
||||||
- [Primitive execution options API
|
|
||||||
reference](../qiskit-ibm-runtime/qiskit_ibm_runtime.options.Options)
|
|
||||||
- [How to run a session
|
|
||||||
topic](../../run/run-jobs-in-session)
|
|
||||||
|
|
||||||
#### 3. Other execution alternatives (non-Runtime)
|
|
||||||
|
|
||||||
This section describes how to use non-Runtime primitives to test an
|
|
||||||
algorithm using local simulation. Let's assume that we want to solve
|
|
||||||
the problem defined above with a local state vector simulation.
|
|
||||||
|
|
||||||
<span id="3a"></span>
|
|
||||||
##### 3.a. Legacy: Using the Qiskit Aer simulator
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.opflow import StateFn, PauliExpectation, CircuitSampler
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
|
|
||||||
# Define the state to sample
|
|
||||||
measurable_expression = StateFn(opflow_op, is_measurement=True).compose(opflow_state)
|
|
||||||
|
|
||||||
# Convert to expectation value calculation object
|
|
||||||
expectation = PauliExpectation().convert(measurable_expression)
|
|
||||||
|
|
||||||
# Define statevector simulator
|
|
||||||
simulator = AerSimulator(method="statevector", shots=100)
|
|
||||||
|
|
||||||
# Inject backend into circuit sampler
|
|
||||||
circuit_sampler = CircuitSampler(simulator).convert(expectation)
|
|
||||||
|
|
||||||
# Evaluate
|
|
||||||
expectation_value = circuit_sampler.eval().real
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("expectation: ", expectation_value)
|
|
||||||
expectation: -1.0636533500290943
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 3.b. Updated: Use the Reference Estimator or Aer Estimator primitive
|
|
||||||
|
|
||||||
The reference `Estimator` lets you perform either an exact or a
|
|
||||||
shot-based noisy simulation based on the `Statevector` class in the
|
|
||||||
`qiskit.quantum_info` module.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Estimator
|
|
||||||
|
|
||||||
estimator = Estimator()
|
|
||||||
|
|
||||||
expectation_value = estimator.run(state, op).result().values
|
|
||||||
|
|
||||||
# for shot-based simulation:
|
|
||||||
expectation_value = estimator.run(state, op, shots=100).result().values
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("expectation: ", expectation_value)
|
|
||||||
expectation: [-1.03134297]
|
|
||||||
```
|
|
||||||
|
|
||||||
You can still access the Aer Simulator through its dedicated
|
|
||||||
`Estimator`. This can be handy for performing simulations with noise
|
|
||||||
models. In this example, the simulation method has been updated to match
|
|
||||||
the result from [3.a](#3a).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_aer.primitives import Estimator # import change
|
|
||||||
|
|
||||||
estimator = Estimator(run_options= {"method": "statevector"})
|
|
||||||
|
|
||||||
expectation_value = estimator.run(state, op, shots=100).result().values
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("expectation: ", expectation_value)
|
|
||||||
expectation: [-1.06365335]
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information on using the Aer primitives, see the [VQE tutorial](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/03_vqe_simulation_with_noise.ipynb).
|
|
||||||
|
|
||||||
For more information about running noisy simulations with the **Runtime primitives**, see the [Noisy simulators in Qiskit Runtime](../../verify/using-ibm-quantum-simulators) topic.
|
|
||||||
|
|
||||||
<span id="sampler-algorithm"></span>
|
|
||||||
## Use Sampler to design an algorithm
|
|
||||||
|
|
||||||
The Sampler primitive is used to design an algorithm that samples
|
|
||||||
circuits and extracts probability distributions.
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
The role of the `Sampler` primitive is two-fold: it acts as an **entry
|
|
||||||
point** to quantum devices or simulators, replacing `backend.run()`.
|
|
||||||
Additionally, it is an **algorithmic abstraction** to extract
|
|
||||||
probability distributions from measurement counts.
|
|
||||||
|
|
||||||
Both `Sampler` and `backend.run()` take in circuits as inputs. The main
|
|
||||||
difference is the format of the output: `backend.run()` outputs
|
|
||||||
**counts**, while `Sampler` processes those counts and outputs the
|
|
||||||
**quasi-probability distribution** associated with them.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
**Backend.run() model:** In this model, you used the `qiskit-ibmq-provider` (now migrated to `qiskit-ibm-provider`) module to access real systems and remote simulators. To run **local** simulations, you could import a specific simulator from `qiskit-aer`. All of them followed the `backend.run()` interface.
|
|
||||||
|
|
||||||
````
|
|
||||||
<details>
|
|
||||||
<summary><a>Code example with `qiskit-ibmq-provider` and `backend.run()`</a></summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit import IBMQ
|
|
||||||
|
|
||||||
# Select provider
|
|
||||||
provider = IBMQ.load_account()
|
|
||||||
|
|
||||||
# Get backend
|
|
||||||
backend = provider.get_backend("ibmq_qasm_simulator") # Use the cloud simulator
|
|
||||||
|
|
||||||
# Run
|
|
||||||
result = backend.run(circuits)
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><a>Code example for `qiskit-aer` & `backend.run()` </a></summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_aer import AerSimulator # former import: from qiskit import Aer
|
|
||||||
|
|
||||||
# Get local simulator backend
|
|
||||||
backend = AerSimulator()
|
|
||||||
|
|
||||||
# Run
|
|
||||||
result = backend.run(circuits)
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
**Primitives model:** Access real systems and remote simulators through the `qiskit-ibm-runtime` Sampler and Estimator *primitives*. To run **local** simulations, import specific local primitives from `qiskit_aer.primitives` and `qiskit.primitives`. All of them follow the `BaseSampler` and `BaseEstimator` interfaces, but **only the Runtime primitives offer access to the Runtime service, sessions, and built-in error mitigation**.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><a>Code example for Runtime Sampler</a></summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
# Define service
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
# Get backend
|
|
||||||
backend = service.backend("ibmq_qasm_simulator") # Use a cloud simulator
|
|
||||||
|
|
||||||
# Define Sampler
|
|
||||||
# (see tutorials more more info on sessions)
|
|
||||||
sampler = Sampler(session=backend)
|
|
||||||
|
|
||||||
# Run Quasi-Probability calculation
|
|
||||||
result = sampler.run(circuits).result()
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><a>Code example for Aer Sampler</a></summary>
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_aer import Sampler
|
|
||||||
|
|
||||||
# Get local simulator Sampler
|
|
||||||
sampler = Sampler()
|
|
||||||
|
|
||||||
# Run Quasi-Probability calculation
|
|
||||||
result = sampler.run(circuits).result()
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
````
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Next, we will show an end-to-end example of sampling a circuit: first,
|
|
||||||
with `backend.run()`, then by using the `Sampler`.
|
|
||||||
|
|
||||||
## End-to-end example
|
|
||||||
|
|
||||||
### 1. Problem definition
|
|
||||||
|
|
||||||
We want to find the probability (or quasi-probability) distribution
|
|
||||||
associated with a quantum state:
|
|
||||||
|
|
||||||
<Admonition type="attention">
|
|
||||||
Important: If you want to use the `Sampler` primitive, the circuit **must contain measurements**.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(4)
|
|
||||||
circuit.h(range(2))
|
|
||||||
circuit.cx(0,1)
|
|
||||||
circuit.measure_all() # measurement!
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Calculate probability distribution on a real device or cloud simulator
|
|
||||||
|
|
||||||
#### 2.a. Legacy: Use backend.run()
|
|
||||||
|
|
||||||
The required steps to reach our goal with `backend.run()` are:
|
|
||||||
|
|
||||||
1. Run circuits
|
|
||||||
2. Get counts from the result object
|
|
||||||
3. Use the counts and shots to calculate the probability distribution
|
|
||||||
|
|
||||||
First, we run the circuit in a cloud simulator and output the result
|
|
||||||
object:
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Replace `ibmq_qasm_simulator` with your device name to see the complete workflow for a real device.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import IBMQ
|
|
||||||
|
|
||||||
# Define provider and backend
|
|
||||||
provider = IBMQ.load_account()
|
|
||||||
backend = provider.get_backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
# Run
|
|
||||||
result = backend.run(circuit, shots=1024).result()
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("result: ", result)
|
|
||||||
result: Result(backend_name='ibmq_qasm_simulator', backend_version='0.11.0',
|
|
||||||
qobj_id='65bb8a73-cced-40c1-995a-8961cc2badc4', job_id='63fc95612751d57b6639f777',
|
|
||||||
success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2,
|
|
||||||
data=ExperimentResultData(counts={'0x0': 255, '0x1': 258, '0x2': 243, '0x3': 268}),
|
|
||||||
header=QobjExperimentHeader(clbit_labels=[['meas', 0], ['meas', 1], ['meas', 2], ['meas', 3]],
|
|
||||||
creg_sizes=[['meas', 4]], global_phase=0.0, memory_slots=4, metadata={}, n_qubits=4,
|
|
||||||
name='circuit-930', qreg_sizes=[['q', 4]], qubit_labels=[['q', 0], ['q', 1], ['q', 2], ['q', 3]]),
|
|
||||||
status=DONE, metadata={'active_input_qubits': [0, 1, 2, 3], 'batched_shots_optimization': False,
|
|
||||||
'device': 'CPU', 'fusion': {'enabled': False}, 'input_qubit_map': [[3, 3], [2, 2], [1, 1], [0, 0]],
|
|
||||||
'measure_sampling': True, 'method': 'stabilizer', 'noise': 'ideal', 'num_clbits': 4, 'num_qubits': 4,
|
|
||||||
'parallel_shots': 1, 'parallel_state_update': 16, 'remapped_qubits': False,
|
|
||||||
'sample_measure_time': 0.001001096}, seed_simulator=2191402198, time_taken=0.002996865)],
|
|
||||||
date=2023-02-27 12:35:00.203255+01:00, status=COMPLETED, header=QobjHeader(backend_name='ibmq_qasm_simulator',
|
|
||||||
backend_version='0.1.547'), metadata={'max_gpu_memory_mb': 0, 'max_memory_mb': 386782, 'mpi_rank': 0,
|
|
||||||
'num_mpi_processes': 1, 'num_processes_per_experiments': 1, 'omp_enabled': True, 'parallel_experiments': 1,
|
|
||||||
'time_taken': 0.003215252, 'time_taken_execute': 0.00303248, 'time_taken_load_qobj': 0.000169435},
|
|
||||||
time_taken=0.003215252, client_version={'qiskit': '0.39.5'})
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we get the probability distribution from the output:
|
|
||||||
|
|
||||||
```python
|
|
||||||
counts = result.get_counts(circuit)
|
|
||||||
quasi_dists = {}
|
|
||||||
for key,count in counts.items():
|
|
||||||
quasi_dists[key] = count/1024
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("counts: ", counts)
|
|
||||||
>>> print("quasi_dists: ", quasi_dists)
|
|
||||||
counts: {'0000': 255, '0001': 258, '0010': 243, '0011': 268}
|
|
||||||
quasi_dists: {'0000': 0.2490234375, '0001': 0.251953125, '0010': 0.2373046875, '0011': 0.26171875}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.b. Updated: Use the Sampler runtime primitive
|
|
||||||
|
|
||||||
While the user-side syntax of the `Sampler` is very similar to
|
|
||||||
`backend.run()`, notice that the workflow is now simplified, as the
|
|
||||||
quasi-probability distribution is returned **directly** (no need to
|
|
||||||
perform post-processing), together with some key metadata.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Replace `ibmq_qasm_simulator` with your device name to see the complete workflow for a real device.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum")
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
sampler = Sampler(session=backend)
|
|
||||||
|
|
||||||
result = sampler.run(circuit, shots=1024).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("result: ", result)
|
|
||||||
>>> print("quasi_dists: ", quasi_dists)
|
|
||||||
result: SamplerResult(quasi_dists=[{0: 0.2802734375, 1: 0.2509765625, 2: 0.232421875, 3: 0.236328125}],
|
|
||||||
metadata=[{'header_metadata': {}, 'shots': 1024, 'readout_mitigation_overhead': 1.0,
|
|
||||||
'readout_mitigation_time': 0.03801989182829857}])
|
|
||||||
quasi_dists: [{0: 0.2802734375, 1: 0.2509765625, 2: 0.232421875, 3: 0.236328125}]
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="attention">
|
|
||||||
Be careful with the output format. With `Sampler`, the states are no longer represented by bit strings, for example, `"11"`, but by integers, for example, `3`. To convert the `Sampler` output to bit strings, you can use the `QuasiDistribution.binary_probabilities()` method, as shown below.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> # convert the output to bit strings
|
|
||||||
>>> binary_quasi_dist = quasi_dists[0].binary_probabilities()
|
|
||||||
>>> print("binary_quasi_dist: ", binary_quasi_dist)
|
|
||||||
binary_quasi_dist: {'0000': 0.2802734375, '0001': 0.2509765625, '0010': 0.232421875, '0011': 0.236328125}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `Sampler` Runtime primitive offers several features and tuning
|
|
||||||
options that do not have a legacy alternative to migrate from, but can
|
|
||||||
help improve your performance and results. For more information, refer
|
|
||||||
to the following:
|
|
||||||
|
|
||||||
- [Error mitigation tutorial](https://learning.quantum.ibm.com/tutorial/error-suppression-and-error-mitigation-with-qiskit-runtime)
|
|
||||||
- [Setting execution options topic](../../run/advanced-runtime-options)
|
|
||||||
- [How to run a session topic](../../run/run-jobs-in-session)
|
|
||||||
|
|
||||||
### 3. Other execution alternatives (non-Runtime)
|
|
||||||
|
|
||||||
The following migration paths use non-Runtime primitives to use local
|
|
||||||
simulation to test an algorithm. Let's assume that we want to use a
|
|
||||||
local state vector simulation to solve the problem defined above.
|
|
||||||
|
|
||||||
#### 3.a. Legacy: Use the Qiskit Aer simulator
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_aer import AerSimulator
|
|
||||||
|
|
||||||
# Define the statevector simulator
|
|
||||||
simulator = AerSimulator(method="statevector")
|
|
||||||
|
|
||||||
# Run and get counts
|
|
||||||
result = simulator.run(circuit, shots=1024).result()
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("result: ", result)
|
|
||||||
result: Result(backend_name='aer_simulator_statevector', backend_version='0.11.2',
|
|
||||||
qobj_id='e51e51bc-96d8-4e10-aa4e-15ee6264f4a0', job_id='c603daa7-2c03-488c-8c75-8c6ea0381bbc',
|
|
||||||
success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2,
|
|
||||||
data=ExperimentResultData(counts={'0x2': 236, '0x0': 276, '0x3': 262, '0x1': 250}),
|
|
||||||
header=QobjExperimentHeader(clbit_labels=[['meas', 0], ['meas', 1], ['meas', 2], ['meas', 3]],
|
|
||||||
creg_sizes=[['meas', 4]], global_phase=0.0, memory_slots=4, metadata={}, n_qubits=4, name='circuit-930',
|
|
||||||
qreg_sizes=[['q', 4]], qubit_labels=[['q', 0], ['q', 1], ['q', 2], ['q', 3]]), status=DONE,
|
|
||||||
seed_simulator=3531074553, metadata={'parallel_state_update': 16, 'parallel_shots': 1,
|
|
||||||
'sample_measure_time': 0.000405246, 'noise': 'ideal', 'batched_shots_optimization': False,
|
|
||||||
'remapped_qubits': False, 'device': 'CPU', 'active_input_qubits': [0, 1, 2, 3], 'measure_sampling': True,
|
|
||||||
'num_clbits': 4, 'input_qubit_map': [[3, 3], [2, 2], [1, 1], [0, 0]], 'num_qubits': 4, 'method': 'statevector',
|
|
||||||
'fusion': {'applied': False, 'max_fused_qubits': 5, 'threshold': 14, 'enabled': True}}, time_taken=0.001981756)],
|
|
||||||
date=2023-02-27T12:38:18.580995, status=COMPLETED, header=QobjHeader(backend_name='aer_simulator_statevector',
|
|
||||||
backend_version='0.11.2'), metadata={'mpi_rank': 0, 'num_mpi_processes': 1, 'num_processes_per_experiments': 1,
|
|
||||||
'time_taken': 0.002216379, 'max_gpu_memory_mb': 0, 'time_taken_execute': 0.002005713, 'max_memory_mb': 65536,
|
|
||||||
'time_taken_load_qobj': 0.000200642, 'parallel_experiments': 1, 'omp_enabled': True},
|
|
||||||
time_taken=0.0025920867919921875)
|
|
||||||
```
|
|
||||||
|
|
||||||
Now let's get the probability distribution from the output:
|
|
||||||
|
|
||||||
```python
|
|
||||||
counts = result.get_counts(circuit)
|
|
||||||
quasi_dists = {}
|
|
||||||
for key,count in counts.items():
|
|
||||||
quasi_dists[key] = count/1024
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("counts: ", counts)
|
|
||||||
>>> print("quasi_dists: ", quasi_dists)
|
|
||||||
counts: {'0010': 236, '0000': 276, '0011': 262, '0001': 250}
|
|
||||||
quasi_dists: {'0010': 0.23046875, '0000': 0.26953125, '0011': 0.255859375, '0001': 0.244140625}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3.b. Updated: Use the Reference Sampler or Aer Sampler primitive
|
|
||||||
|
|
||||||
The reference `Sampler` lets you perform an exact or a shot-based noisy
|
|
||||||
simulation based on the `Statevector` class in the `qiskit.quantum_info`
|
|
||||||
module.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
sampler = Sampler()
|
|
||||||
|
|
||||||
result = sampler.run(circuit).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("result: ", result)
|
|
||||||
>>> print("quasi_dists: ", quasi_dists)
|
|
||||||
result: SamplerResult(quasi_dists=[{0: 0.249999999999, 1: 0.249999999999,
|
|
||||||
2: 0.249999999999, 3: 0.249999999999}], metadata=[{}])
|
|
||||||
quasi_dists: [{0: 0.249999999999, 1: 0.249999999999, 2: 0.249999999999,
|
|
||||||
3: 0.249999999999}]
|
|
||||||
```
|
|
||||||
|
|
||||||
If shots are specified, this primitive outputs a shot-based simulation
|
|
||||||
(no longer exact):
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
sampler = Sampler()
|
|
||||||
|
|
||||||
result = sampler.run(circuit, shots=1024).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("result: ", result)
|
|
||||||
>>> print("quasi_dists: ", quasi_dists)
|
|
||||||
result: SamplerResult(quasi_dists=[{0: 0.2490234375, 1: 0.2578125,
|
|
||||||
2: 0.2431640625, 3: 0.25}], metadata=[{'shots': 1024}])
|
|
||||||
quasi_dists: [{0: 0.2490234375, 1: 0.2578125, 2: 0.2431640625, 3: 0.25}]
|
|
||||||
```
|
|
||||||
|
|
||||||
You can still access the Aer simulator through its dedicated `Sampler`.
|
|
||||||
This can be handy for performing simulations with noise models. In this
|
|
||||||
example, the simulation method has been updated to match the result from
|
|
||||||
3.a.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_aer.primitives import Sampler as AerSampler # import change!
|
|
||||||
|
|
||||||
sampler = AerSampler(run_options= {"method": "statevector"})
|
|
||||||
|
|
||||||
result = sampler.run(circuit, shots=1024).result()
|
|
||||||
quasi_dists = result.quasi_dists
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> print("result: ", result)
|
|
||||||
>>> print("quasi_dists: ", quasi_dists)
|
|
||||||
result: SamplerResult(quasi_dists=[{1: 0.2802734375, 2: 0.2412109375, 0: 0.2392578125,
|
|
||||||
3: 0.2392578125}], metadata=[{'shots': 1024, 'simulator_metadata':
|
|
||||||
{'parallel_state_update': 16, 'parallel_shots': 1, 'sample_measure_time': 0.000409608,
|
|
||||||
'noise': 'ideal', 'batched_shots_optimization': False, 'remapped_qubits': False,
|
|
||||||
'device': 'CPU', 'active_input_qubits': [0, 1, 2, 3], 'measure_sampling': True,
|
|
||||||
'num_clbits': 4, 'input_qubit_map': [[3, 3], [2, 2], [1, 1], [0, 0]], 'num_qubits': 4,
|
|
||||||
'method': 'statevector', 'fusion': {'applied': False, 'max_fused_qubits': 5,
|
|
||||||
'threshold': 14, 'enabled': True}}}])
|
|
||||||
quasi_dists: [{1: 0.2802734375, 2: 0.2412109375, 0: 0.2392578125, 3: 0.2392578125}]
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
>>> # Convert the output to bit strings
|
|
||||||
>>> binary_quasi_dist = quasi_dists[0].binary_probabilities()
|
|
||||||
>>> print("binary_quasi_dist: ", binary_quasi_dist)
|
|
||||||
binary_quasi_dist: {'0001': 0.2802734375, '0010': 0.2412109375, '0000': 0.2392578125, '0011': 0.2392578125}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information, see [Noisy simulators in Qiskit Runtime](../../verify/using-ibm-quantum-simulators).
|
|
|
@ -1,102 +0,0 @@
|
||||||
---
|
|
||||||
title: Migrate from qiskit_ibm_provider to qiskit_ibm_runtime
|
|
||||||
description: How to migrate `backend.run()` from Qiskit IBM Provider to Qiskit IBM Runtime
|
|
||||||
---
|
|
||||||
|
|
||||||
# Migrate `backend.run()` from `qiskit_ibm_provider` to `qiskit_ibm_runtime`
|
|
||||||
|
|
||||||
The Qiskit Runtime interface includes two packages:
|
|
||||||
Qiskit IBM Provider (the [`qiskit_ibm_provider`](../qiskit-ibm-provider) package) and
|
|
||||||
Qiskit IBM Runtime (the [`qiskit_ibm_runtime`](../qiskit-ibm-runtime) package). Until now,
|
|
||||||
primitives (`Sampler` and `Estimator`)
|
|
||||||
were run in Runtime. Custom circuits that were manually transpiled and used `IBMBackend.run()`
|
|
||||||
were run in Provider.
|
|
||||||
|
|
||||||
In the `qiskit-ibm-runtime` 0.15 release, we added support for running custom circuits using `IBMBackend.run()` in Runtime,
|
|
||||||
so users can run all programs through Runtime.
|
|
||||||
|
|
||||||
This guide describes how to migrate code that implemented `IBMBackend.run()`
|
|
||||||
using Qiskit IBM Provider to use Qiskit IBM Runtime instead.
|
|
||||||
|
|
||||||
**Example 1: Straightforward execution of IBMBackend.run()**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import *
|
|
||||||
from qiskit.compiler import transpile, assemble
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2, 2)
|
|
||||||
circuit.h(0)
|
|
||||||
circuit.cx(0, 1)
|
|
||||||
circuit.measure_all()
|
|
||||||
```
|
|
||||||
|
|
||||||
In Provider, the code is:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_provider import IBMProvider
|
|
||||||
|
|
||||||
provider = IBMProvider()
|
|
||||||
backend = provider.get_backend("ibmq_qasm_simulator")
|
|
||||||
transpiled_circuit = transpile(circuit, backend=backend)
|
|
||||||
job = backend.run(transpiled_circuit)
|
|
||||||
print(job.result())
|
|
||||||
```
|
|
||||||
|
|
||||||
In Runtime, the code is:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum")
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
transpiled_circuit = transpile(circuit, backend=backend)
|
|
||||||
job = backend.run(transpiled_circuit)
|
|
||||||
print(job.result())
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example 2: Execution of backend.run() within a session:**
|
|
||||||
|
|
||||||
This section of code is identical in Provider and in Runtime.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with backend.open_session() as session:
|
|
||||||
job1 = backend.run(transpiled_circuit)
|
|
||||||
job2 = backend.run(transpiled_circuit)
|
|
||||||
print(job1.session_id)
|
|
||||||
print(job2.session_id)
|
|
||||||
backend.cancel_session()
|
|
||||||
```
|
|
||||||
|
|
||||||
Sessions are implemented differently in `IBMBackend` than when using primitives.
|
|
||||||
Therefore, we cannot run a primitive and use backend.run() within a single session. If you specify both, one will be run outside of the session.
|
|
||||||
|
|
||||||
**Example 3: Primitive session containing backend.run:**
|
|
||||||
|
|
||||||
In this example, `sampler` is run within session, but `backend` is run independently
|
|
||||||
of the session.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Session, Sampler
|
|
||||||
|
|
||||||
with Session(backend=backend) as session:
|
|
||||||
sampler = Sampler(session=session)
|
|
||||||
job1 = sampler.run(transpiled_circuit)
|
|
||||||
job2 = backend.run(transpiled_circuit) # runs outside the session
|
|
||||||
print(job1.session_id)
|
|
||||||
print(job2.session_id) # is None
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example 4: `Backend` session containing Sampler:**
|
|
||||||
|
|
||||||
In this example, `backend` is run within a session, but `sampler` is run independently
|
|
||||||
of the session.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with backend.open_session() as session:
|
|
||||||
sampler = Sampler(backend=backend)
|
|
||||||
job1 = sampler.run(transpiled_circuit) # runs outside the session
|
|
||||||
job2 = backend.run(transpiled_circuit)
|
|
||||||
session_id = session.session_id
|
|
||||||
print(job1.session_id) # is None
|
|
||||||
print(job2.session_id)
|
|
||||||
```
|
|
|
@ -1,404 +0,0 @@
|
||||||
---
|
|
||||||
title: Migrate to using Qiskit Runtime primitives
|
|
||||||
description: Migrate from using backend.run to using Qiskit Runtime primitives
|
|
||||||
in_page_toc_max_heading_level: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
<span id="migrate-to-qr"></span>
|
|
||||||
# Migrate to using Qiskit Runtime primitives
|
|
||||||
|
|
||||||
This guide describes key patterns of behavior and use cases with code
|
|
||||||
examples to help you migrate code from the legacy `qiskit-ibmq-provider`
|
|
||||||
package to use the Qiskit Runtime primitives.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
There are two methods for accessing IBM Quantum systems. First, the `qiskit-ibm-provider` package provides the `backend.run()` interface, allowing direct access to IBM Quantum systems with no pre- or post-processing involved. This level of access is suitable for those users who want **precise control** over circuit execution and result processing. This level of access is needed for those at the level of kernel developer who are looking to develop, for example, circuit optimization routines or error mitigation techniques, or who want to characterize quantum systems.
|
|
||||||
|
|
||||||
In contrast, Qiskit Runtime is designed to **streamline algorithm and application construction** by removing the need for users to understand technical hardware and low-level software details. Advanced processing techniques for error suppression and mitigation are automatically applied, giving users high-fidelity results without the burden of having to code these routines themselves. Sessions within Qiskit Runtime allow users to run iterative algorithm circuits back to back, or batch collections of circuits without having to re-queue each job. This results in more efficient quantum processor use and reduces the time users spend running complex computations.
|
|
||||||
|
|
||||||
<Admonition type="note">backend.run is required for running dynamic circuits.</Admonition>
|
|
||||||
|
|
||||||
Primitives are the recommended tool to write quantum algorithms, as they
|
|
||||||
encapsulate common device queries seen in application packages and allow
|
|
||||||
for managed performance through the Qiskit Runtime service. However, if
|
|
||||||
your algorithm requires more granular information, such as pre-shot
|
|
||||||
measurements, the primitives might not provide the desired abstraction
|
|
||||||
level.
|
|
||||||
|
|
||||||
The Qiskit Runtime primitives implement the reference `Sampler` and
|
|
||||||
`Estimator` interfaces found in
|
|
||||||
[qiskit.primitives](../qiskit/primitives).
|
|
||||||
These interfaces let you switch between primitive implementations with
|
|
||||||
minimal code changes. Different primitive implementations can be found
|
|
||||||
in the `qiskit`, `qiskit_aer`, and `qiskit_ibm_runtime` libraries. Each
|
|
||||||
implementation serves a specific purpose:
|
|
||||||
|
|
||||||
- The primitives in `qiskit` can perform local state vector
|
|
||||||
simulations - useful for quickly prototyping algorithms.
|
|
||||||
- The primitives in `qiskit_aer` give access to the local Aer
|
|
||||||
simulators for tasks such as noisy simulation.
|
|
||||||
- The primitives in `qiskit_ibm_runtime` provide access to cloud
|
|
||||||
simulators and real hardware through the Qiskit Runtime service.
|
|
||||||
They include exclusive features such as built-in circuit
|
|
||||||
optimization and error mitigation support.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The **only primitives that provide access to the Qiskit Runtime service** are those imported from `qiskit_ibm_runtime` (Qiskit Runtime Primitives).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
When migrating, the key to writing an equivalent algorithm using
|
|
||||||
primitives is to first identify what is the minimal unit of information
|
|
||||||
your algorithm is based on:
|
|
||||||
|
|
||||||
- If it uses an **expectation value**, you will need an `Estimator`.
|
|
||||||
- If it uses a **probability distribution** (from sampling the device), you will need a `Sampler`.
|
|
||||||
|
|
||||||
After determining which primitive to use, identify where the algorithm
|
|
||||||
accesses the system. Look for the call to `backend.run()`. Next, you
|
|
||||||
will replace this call with the respective primitive call, as shown in
|
|
||||||
the following examples.
|
|
||||||
|
|
||||||
This guide is for algorithm developers who need to refactor algorithms to use primitives instead of `backend.run()`. See examples here:
|
|
||||||
|
|
||||||
```
|
|
||||||
- [Update code that performs circuit sampling](qiskit-runtime-examples#sampler-algorithm)
|
|
||||||
- [Update code that calculates expectation values](qiskit-runtime-examples#estimator-algorithm)
|
|
||||||
```
|
|
||||||
|
|
||||||
The following topics are use cases with code migration examples:
|
|
||||||
|
|
||||||
- [Update parameter values while running](#parm-circ)
|
|
||||||
- [Algorithm tuning options (shots, transpilation, error mitigation)](../../run/advanced-runtime-options)
|
|
||||||
|
|
||||||
## FAQs
|
|
||||||
|
|
||||||
Users might have the following questions when planning to migrate their
|
|
||||||
code to Qiskit Runtime:
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>How do the Qiskit Runtime primitives differ from backend.run?</summary>
|
|
||||||
|
|
||||||
There are two methods for accessing IBM Quantum systems. First, the qiskit-ibm-provider package provides the backend.run() interface, allowing direct access to IBM Quantum systems with no pre- or post-processing involved. This level of access is suitable for those users who want precise control over circuit execution and result processing. This level of access is needed for those looking to work at the level Kernel developer developing, for example, circuit optimization routines, error mitigation techniques, or characterizing quantum systems.
|
|
||||||
|
|
||||||
In contrast, Qiskit Runtime is designed to streamline algorithm and application construction by removing the need for users to understand technical hardware and low-level software details. Advanced processing techniques for error suppression and mitigation are automatically applied, giving users high-fidelity results without the burden of having to code these routines themselves. The inclusion of sessions within Qiskit Runtime allows users to run iterative algorithm circuits back to back, or batch collections of circuits without having to re-queue each job. This results in more efficient quantum processor utilization and reduces the total amount of time users spend running complex computations.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Which channel should I use?</summary>
|
|
||||||
|
|
||||||
After deciding to use Qiskit Runtime primitives, the user must determine
|
|
||||||
whether to access Qiskit Runtime through IBM Cloud or IBM Quantum
|
|
||||||
Platform. Some information that might help you decide includes:
|
|
||||||
|
|
||||||
- The available plans:
|
|
||||||
- Qiskit Runtime is available in both the Open (free access) or Premium (contract-based paid access) plan on IBM Quantum Platform. See [IBM Quantum access plans](https://www.ibm.com/quantum/access-plans) for details.
|
|
||||||
- Qiskit Runtime is accessible through the Lite (free access) or Standard (pay-as-you-go access) plan in IBM Cloud. See [Qiskit Runtime plans](https://cloud.ibm.com/docs/quantum-computing?topic=quantum-computing-plans) on IBM Cloud for details.
|
|
||||||
- The use case requirements:
|
|
||||||
- IBM Quantum Platform offers a visual circuit composer (Quantum Composer) and a Jupyter Notebook environment (Quantum Lab).
|
|
||||||
- IBM Cloud offers a cloud native service that is ideal if users need to integrate quantum capabilities with other cloud services.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>How do I set up my channel?</summary>
|
|
||||||
|
|
||||||
After deciding which channel to use to interact with Qiskit Runtime, you
|
|
||||||
can get set up on either platform by following the steps in [Install and set up.](../../start/install)
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Should I modify the Qiskit Terra algorithms?</summary>
|
|
||||||
|
|
||||||
As of v0.22, [Qiskit Terra algorithms](https://github.com/Qiskit/qiskit/tree/stable/0.46/qiskit/algorithms) use Qiskit Runtime primitives. Thus, there is no need for users to
|
|
||||||
modify amplitude estimators or any other Qiskit Terra algorithms.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Which primitive should I use?</summary>
|
|
||||||
|
|
||||||
When choosing which primitive to use, you first need to understand
|
|
||||||
whether the algorithm uses a **quasi-probability distribution** sampled
|
|
||||||
from a quantum state (a list of quasi-probabilities), or an
|
|
||||||
**expectation value** of a certain observable with respect to a
|
|
||||||
quantum state (a real number).
|
|
||||||
|
|
||||||
A probability distribution is often of interest in optimization problems
|
|
||||||
that return a classical bit string, encoding a certain solution to a
|
|
||||||
problem at hand. In these cases, you might be interested in finding a
|
|
||||||
bit string that corresponds to a ket value with the largest probability
|
|
||||||
of being measured from a quantum state, for example.
|
|
||||||
|
|
||||||
An expectation value of an observable could be the target quantity in
|
|
||||||
scenarios where knowing a quantum state is not relevant. This often
|
|
||||||
occurs in optimization problems or chemistry applications. For example,
|
|
||||||
when trying to discover the extremal energy of a system.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Migrate setup from qiskit-ibmq-provider
|
|
||||||
|
|
||||||
This guide describes how to migrate code from the legacy IBMQ provider
|
|
||||||
`qiskit-ibmq-provider` package to use Qiskit Runtime
|
|
||||||
`qiskit-ibm-runtime`. This guide includes instructions to
|
|
||||||
migrate legacy runtime programs to the new syntax. However, the ability
|
|
||||||
to use custom uploaded programs has been deprecated and has been replaced with Quantum Serverless patterns. For instructions to migrate, see [Converting from Qiskit Runtime Programs.](https://qiskit-extensions.github.io/quantum-serverless/migration/migration_from_qiskit_runtime_programs.html)
|
|
||||||
|
|
||||||
### Changes in Class name and location
|
|
||||||
|
|
||||||
The classes related to Qiskit Runtime that used to be included in
|
|
||||||
`qiskit-ibmq-provider` are now part of `qiskit-ibm-runtime`. Before, the
|
|
||||||
provider used to populate the `qiskit.providers.ibmq.runtime` namespace
|
|
||||||
with objects for Qiskit Runtime. These now live in the
|
|
||||||
`qiskit_ibm_runtime` module.
|
|
||||||
|
|
||||||
The module from which the classes are imported has changed. The
|
|
||||||
following table contains example access patterns in
|
|
||||||
`qiskit.providers.ibmq.runtime` and their new form in
|
|
||||||
`qiskit_ibm_runtime`:
|
|
||||||
|
|
||||||
| class in qiskit-ibmq-provider | class in qiskit-ibm-runtime | Notes |
|
|
||||||
| ------------------------------------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| qiskit.providers.ibmq.runtime.IBMRuntimeService | qiskit_ibm_runtime.QiskitRuntimeService | IBMRuntimeService class was removed from qiskit-ibm-runtime 0.6 and replaced by the new class in qiskit-ibm-runtime. |
|
|
||||||
| qiskit.providers.ibmq.runtime.RuntimeJob | qiskit_ibm_runtime.RuntimeJob | |
|
|
||||||
| qiskit.providers.ibmq.runtime.RuntimeProgram | qiskit_ibm_runtime.RuntimeProgram | |
|
|
||||||
| qiskit.providers.ibmq.runtime.UserMessenger | qiskit_ibm_runtime.program.UserMessenger | New location: qiskit_ibm_runtime.program |
|
|
||||||
| qiskit.providers.ibmq.runtime.ProgramBackend | qiskit_ibm_runtime.program.ProgramBackend | New location: qiskit_ibm_runtime.program |
|
|
||||||
| qiskit.providers.ibmq.runtime.ResultDecoder | qiskit_ibm_runtime.program.ResultDecoder | New location: qiskit_ibm_runtime.program |
|
|
||||||
| qiskit.providers.ibmq.runtime.RuntimeEncoder | qiskit_ibm_runtime.RuntimeEncoder | |
|
|
||||||
| qiskit.providers.ibmq.runtime.RuntimeDecoder | qiskit_ibm_runtime.RuntimeDecoder | |
|
|
||||||
| qiskit.providers.ibmq.runtime.ParameterNamespace | qiskit_ibm_runtime.ParameterNamespace | |
|
|
||||||
| qiskit.providers.ibmq.runtime.RuntimeOptions | qiskit_ibm_runtime.RuntimeOptions | |
|
|
||||||
|
|
||||||
### Import path
|
|
||||||
|
|
||||||
The import path has changed as follows:
|
|
||||||
|
|
||||||
**Legacy**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import IBMQ
|
|
||||||
```
|
|
||||||
|
|
||||||
**Updated**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
```
|
|
||||||
|
|
||||||
### Save accounts
|
|
||||||
|
|
||||||
Use the updated code to work save accounts.
|
|
||||||
|
|
||||||
**Legacy**
|
|
||||||
|
|
||||||
```python
|
|
||||||
IBMQ.save_account("<IQX_TOKEN>", overwrite=True)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Updated**
|
|
||||||
|
|
||||||
The new syntax accepts credentials for
|
|
||||||
Qiskit Runtime on IBM Cloud or IBM Quantum Platform. For more
|
|
||||||
information on retrieving account credentials, see [Install and set up](../../start/install).
|
|
||||||
|
|
||||||
```python
|
|
||||||
# IBM Cloud channel
|
|
||||||
|
|
||||||
QiskitRuntimeService.save_account(channel="ibm_cloud", token="<IBM Cloud API key>", instance="<IBM Cloud CRN>", overwrite=True)
|
|
||||||
|
|
||||||
# IBM Quantum channel; set to default
|
|
||||||
|
|
||||||
QiskitRuntimeService.save_account(channel="ibm_quantum", token="<IQP_TOKEN>", overwrite=True, default=true)
|
|
||||||
```
|
|
||||||
|
|
||||||
Additionally, you can now name your saved credentials and load the credentials by name.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Save different accounts for open and premium access
|
|
||||||
|
|
||||||
QiskitRuntimeService.save_account(channel="ibm_quantum", token="<IQX_TOKEN>", instance="h1/g1/p1", name="premium")
|
|
||||||
QiskitRuntimeService.save_account(channel="ibm_quantum", token="<IQX_TOKEN>", instance="h2/g2/p2", name="open")
|
|
||||||
|
|
||||||
# Load the "open" credentials
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(name="open")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Load accounts
|
|
||||||
|
|
||||||
Use the updated code to load accounts.
|
|
||||||
|
|
||||||
**Legacy**
|
|
||||||
|
|
||||||
```python
|
|
||||||
IBMQ.load_account()
|
|
||||||
```
|
|
||||||
|
|
||||||
**Updated**
|
|
||||||
|
|
||||||
The new syntax combines the functionality from `load_account()` and
|
|
||||||
`get_provider()` in one statement. The `channel` input parameter is
|
|
||||||
optional. If multiple accounts have been saved in one device and no
|
|
||||||
`channel` is provided, the default is `"ibm_cloud"`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# To access saved credentials for the IBM cloud channel
|
|
||||||
service = QiskitRuntimeService(channel="ibm_cloud")
|
|
||||||
|
|
||||||
# To access saved credentials for the IBM quantum channel
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Channel selection (get a provider)
|
|
||||||
|
|
||||||
Use the updated code to select a channel.
|
|
||||||
|
|
||||||
**Legacy**
|
|
||||||
|
|
||||||
```python
|
|
||||||
provider = IBMQ.get_provider(project="my_project", group="my_group", hub="my_hub")
|
|
||||||
```
|
|
||||||
|
|
||||||
**Updated**
|
|
||||||
|
|
||||||
The new syntax combines the functionality from `load_account()` and
|
|
||||||
`get_provider()` in one statement. When using the `ibm_quantum` channel,
|
|
||||||
the `hub`, `group`, and `project` are specified through the new
|
|
||||||
`instance` keyword.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# To access saved credentials for the IBM quantum channel and select an instance
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum", instance="my_hub/my_group/my_project")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get the system or simulator
|
|
||||||
|
|
||||||
Use the updated code to view systems and simulators.
|
|
||||||
|
|
||||||
**Legacy**
|
|
||||||
|
|
||||||
```python
|
|
||||||
provider = IBMQ.get_provider(hub="h1", group="g1", project="p1")
|
|
||||||
backend = provider.get_backend("ibm_backend")
|
|
||||||
```
|
|
||||||
|
|
||||||
**Updated**
|
|
||||||
|
|
||||||
```python
|
|
||||||
# You can specify the instance in service.backend() instead of initializing a new service
|
|
||||||
backend = service.backend("ibm_backend", instance="h1/g1/p1")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Upload, view, or delete custom prototype programs
|
|
||||||
|
|
||||||
This function has been replaced with Quantum Serverless patterns. For instructions to migrate, see [Converting from Qiskit Runtime Programs.](https://qiskit-extensions.github.io/quantum-serverless/migration/migration_from_qiskit_runtime_programs.html)
|
|
||||||
|
|
||||||
<span id="parm-circ"></span>
|
|
||||||
## Parametrized circuits with primitives
|
|
||||||
|
|
||||||
Parametrized circuits are a commonly used tool for quantum algorithm
|
|
||||||
design. Because `backend.run()` did not accept parametrized
|
|
||||||
circuits, the parameter binding step had to be integrated in the
|
|
||||||
algorithm workflow. The primitives can perform the parameter binding
|
|
||||||
step internally, which results in a simplification of the algorithm-side
|
|
||||||
logic.
|
|
||||||
|
|
||||||
The following example summarizes the new workflow for managing
|
|
||||||
parametrized circuits.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
Let's define a parametrized circuit:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit import QuantumCircuit, ParameterVector
|
|
||||||
|
|
||||||
n = 3
|
|
||||||
thetas = ParameterVector('θ',n)
|
|
||||||
|
|
||||||
qc = QuantumCircuit(n, 1)
|
|
||||||
qc.h(0)
|
|
||||||
|
|
||||||
for i in range(n-1):
|
|
||||||
qc.cx(i, i+1)
|
|
||||||
|
|
||||||
for i,t in enumerate(thetas):
|
|
||||||
qc.rz(t, i)
|
|
||||||
|
|
||||||
for i in reversed(range(n-1)):
|
|
||||||
qc.cx(i, i+1)
|
|
||||||
|
|
||||||
qc.h(0)
|
|
||||||
qc.measure(0, 0)
|
|
||||||
|
|
||||||
qc.draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
We want to assign the following parameter values to the circuit:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
theta_values = [np.pi/2, np.pi/2, np.pi/2]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Legacy
|
|
||||||
|
|
||||||
Previously, the parameter values had to be bound to their respective
|
|
||||||
circuit parameters prior to calling `backend.run()`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import Aer
|
|
||||||
|
|
||||||
bound_circuit = qc.bind_parameters(theta_values)
|
|
||||||
bound_circuit.draw()
|
|
||||||
|
|
||||||
backend = Aer.get_backend('aer_simulator')
|
|
||||||
job = backend.run(bound_circuit)
|
|
||||||
counts = job.result().get_counts()
|
|
||||||
print(counts)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Primitives
|
|
||||||
|
|
||||||
Now, the primitives take in parametrized circuits directly, together
|
|
||||||
with the parameter values, and the parameter assignment operation can be
|
|
||||||
performed more efficiently on the server side of the primitive.
|
|
||||||
|
|
||||||
This feature is particularly interesting when working with iterative
|
|
||||||
algorithms because the parametrized circuit remains unchanged between
|
|
||||||
calls while the parameter values change. The primitives can transpile
|
|
||||||
once and then cache the unbound circuit, using classical resources more
|
|
||||||
efficiently. Moreover, only the updated parameters are transferred to
|
|
||||||
the cloud, saving additional bandwidth.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
sampler = Sampler()
|
|
||||||
job = sampler.run(qc, theta_values)
|
|
||||||
result = job.result().quasi_dists
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Algorithm tuning
|
|
||||||
|
|
||||||
One of the advantages of the primitives is that they abstract away the
|
|
||||||
circuit execution setup so that algorithm developers can focus on the
|
|
||||||
pure algorithmic components. However, sometimes, to get the most out of
|
|
||||||
an algorithm, you might want to tune certain primitive options. For details, see [Advanced runtime options](../../run/advanced-runtime-options).
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Review some [migration examples](qiskit-runtime-examples).
|
|
||||||
- [Get started with Estimator.](../../run/primitives-get-started#start-estimator)
|
|
||||||
- [Get started with Sampler.](../../run/primitives-get-started#start-sampler)
|
|
||||||
- Explore [sessions.](../../run/sessions)
|
|
||||||
- [Run a primitive in a session.](../../run/run-jobs-in-session)
|
|
||||||
- Experiment with the [Submit pre-transpiled circuits tutorial.](https://learning.quantum.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives)
|
|
||||||
|
|
||||||
</Admonition>
|
|
|
@ -1,86 +0,0 @@
|
||||||
{
|
|
||||||
"title": "構築",
|
|
||||||
"collapsed": true,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "はじめに",
|
|
||||||
"url": "/build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Qiskit による回路の構築",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "回路ライブラリー",
|
|
||||||
"url": "/build/circuit-library"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "回路の構築",
|
|
||||||
"url": "/build/circuit-construction"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "回路の可視化",
|
|
||||||
"url": "/build/circuit-visualization"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "古典的なフィードフォワードと制御フロー",
|
|
||||||
"url": "/build/classical-feedforward-and-control-flow"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ユニタリー演算子の合成",
|
|
||||||
"url": "/build/unitary-synthesis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Qiskit でのビット順序",
|
|
||||||
"url": "/build/bit-ordering"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Qiskit による演算子の構築",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "演算子モジュールの概要",
|
|
||||||
"url": "/build/operators-overview"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "パウリ基底での観測量の指定",
|
|
||||||
"url": "/build/specify-observables-pauli"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "その他の回路構築ツール",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "パルススケジュール",
|
|
||||||
"url": "/build/pulse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "OpenQASM",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "OpenQASM の導入",
|
|
||||||
"url": "/build/introduction-to-qasm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "OpenQASM 2 と Qiskit",
|
|
||||||
"url": "/build/interoperate-qiskit-qasm2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "OpenQASM 3 と Qiskit",
|
|
||||||
"url": "/build/interoperate-qiskit-qasm3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "OpenQASM 3 特徴テーブル",
|
|
||||||
"url": "/build/qasm-feature-table"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "OpenQASM 3.x ライブ仕様",
|
|
||||||
"url": "https://openqasm.com/"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,167 +0,0 @@
|
||||||
---
|
|
||||||
title: Qiskit でのビット順序
|
|
||||||
description: Qiskit の順序付け規則とその規則を選択した理由について学習します
|
|
||||||
---
|
|
||||||
|
|
||||||
# Qiskit でのビット順序
|
|
||||||
|
|
||||||
$n$ ビット(または量子ビット)のセットがある場合、通常、各ビットに $0
|
|
||||||
\\rightarrow n-1$ とラベル付けします。 それぞれのソフトウェアやリソースは、コンピューターメモリー内と画面上に表示されるときにこれらのビットをどのように順序付けるかを選択する必要があります。
|
|
||||||
|
|
||||||
## Qiskit の規則
|
|
||||||
|
|
||||||
様々なシナリオで Qiskit がビットをどのように順序付けるかを説明します。
|
|
||||||
|
|
||||||
### 量子回路
|
|
||||||
|
|
||||||
`QuantumCircuit` クラスは、リスト(`QuantumCircuit.qubits`)に量子ビットを格納しています。 このリストの量子ビットのインデックスが
|
|
||||||
量子ビットのラベルとなります。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.qubits[0] # qubit "0"
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Qubit(QuantumRegister(2, 'q'), 0)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 回路図
|
|
||||||
|
|
||||||
回路図では、量子ビット $0$ が最上位の量子ビットであり、量子ビット $n$ が最下位の量子ビットです。 これは `QuantumCircuit.draw` の `reverse_bits` 引数で変更できます([Qiskit での順序の変更](#change-ordering-in-qiskit)をご覧ください)。
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc.x(1)
|
|
||||||
qc.draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
q_0: ─────
|
|
||||||
┌───┐
|
|
||||||
q_1: ┤ X ├
|
|
||||||
└───┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 整数
|
|
||||||
|
|
||||||
ビットを数値として解釈する場合、ビット $0$ は最下位ビット、ビット $n$ は最上位ビットとなります。 各ビットには値 $2^\\text{label}$ があるため、
|
|
||||||
コーディングの際に役立ちます(ラベルは `QuantumCircuit.qubits`
|
|
||||||
の量子ビットのインデックス)。 例えば、次の回路の実行は、ビット $0$ が `0`、
|
|
||||||
ビット $1$ が `1` となります。 これは 10 進整数 `2`(確率 `1.0` で測定)として解釈されます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
qc.measure_all()
|
|
||||||
Sampler().run(qc).result().quasi_dists[0]
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
{2: 1.0}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 文字列
|
|
||||||
|
|
||||||
ビット(または量子ビット)のリストを文字列として表示または解釈する場合、ビット $n$ は左端のビット、$0$ は右端のビットとなります。 これは通常、最上位の桁を左に数字を書くためであり、Qiskit ではビット $n$ が最上位ビットとして解釈されるためです。
|
|
||||||
|
|
||||||
例えば、次のセルは、単一量子ビット状態の文字列から `Statevector`
|
|
||||||
を定義しています。 この場合、量子ビット $0$ は状態 $|{+}\\rangle$ であり、
|
|
||||||
量子ビット $1$ は 状態 $|0\\rangle$ にあります。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.quantum_info import Statevector
|
|
||||||
sv = Statevector.from_label("0+")
|
|
||||||
sv.probabilities_dict()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
{'00': 0.4999999999999999, '01': 0.4999999999999999}
|
|
||||||
```
|
|
||||||
|
|
||||||
左端のビットがビット $0$ であることを期待するにもかかわらず、通常はビット $n$ を表すため、これはたまにビットの文字列を解釈する際に混乱を招くことがあります。
|
|
||||||
|
|
||||||
### 状態ベクトル行列
|
|
||||||
|
|
||||||
状態ベクトルを複素数のリスト(振幅)として表す場合、Qiskit はこれらの振幅を、インデックス $x$ の振幅が計算基底状態 $|x\\rangle$ を表すように順序付けます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
print(sv[1]) # amplitude of state |01>
|
|
||||||
print(sv[2]) # amplitude of state |10>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
(0.7071067811865475+0j)
|
|
||||||
0j
|
|
||||||
```
|
|
||||||
|
|
||||||
### ゲート
|
|
||||||
|
|
||||||
Qiskit の各ゲートは、独自の方法で量子ビットのリストを解釈できますが、制御ゲートは通常 `(制御, ターゲット)` の規則に従います。
|
|
||||||
|
|
||||||
例えば、次のセルは、量子ビット $0$ が制御で量子ビット $1$ がターゲット
|
|
||||||
であり制御Xゲートを追加します。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.cx(0, 1)
|
|
||||||
qc.draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
q_0: ──■──
|
|
||||||
┌─┴─┐
|
|
||||||
q_1: ┤ X ├
|
|
||||||
└───┘
|
|
||||||
```
|
|
||||||
|
|
||||||
Qiskit のこれまでに述べたすべての規則に従うと、この CX-gate は変換 $|01\\rangle \\leftrightarrow |11\\rangle$ を実行するため、以下の行列を持ちます。
|
|
||||||
|
|
||||||
$$
|
|
||||||
\\begin{pmatrix}
|
|
||||||
1 & 0 & 0 & 0 \\
|
|
||||||
0 & 0 & 0 & 1 \\
|
|
||||||
0 & 0 & 1 & 0 \\
|
|
||||||
0 & 1 & 0 & 0 \\
|
|
||||||
\\end{pmatrix}
|
|
||||||
$$
|
|
||||||
|
|
||||||
## Qiskit での順序の変更
|
|
||||||
|
|
||||||
量子ビットを使って逆順で回路を描画するには(量子ビット $0$ を下)、`reverse_bits` 引数を使用します。 これは生成された図のみに影響し、回路には影響しないため、X-gate はそのまま量子ビット $0$ に対して動作します。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.x(0)
|
|
||||||
qc.draw(reverse_bits=True)
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
q_1: ─────
|
|
||||||
┌───┐
|
|
||||||
q_0: ┤ X ├
|
|
||||||
└───┘
|
|
||||||
```
|
|
||||||
|
|
||||||
`reverse_bits` メソッドを使って、量子ビットのラベルが反転した状態で新しい回路を返すことができます(元の回路は変更されません)。
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc.reverse_bits().draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
q_0: ─────
|
|
||||||
┌───┐
|
|
||||||
q_1: ┤ X ├
|
|
||||||
└───┘
|
|
||||||
```
|
|
||||||
|
|
||||||
この新しい回路では、X-gate は量子ビット $1$ に対して動作することに注意してください。
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Grover's Algorithm(グローバーのアルゴリズム)](https://learning.quantum.ibm.com/tutorial/grovers-algorithm)チュートリアルで、回路の使用例をご覧ください。
|
|
||||||
- [QuantumCircuit API](/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit) リファレンスを詳しくご覧ください。
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,22 +0,0 @@
|
||||||
---
|
|
||||||
title: はじめに
|
|
||||||
description: Qiskit 量子回路、演算子、波形パルス、または OpenQASM を使用して量子プログラムをビルドします。
|
|
||||||
---
|
|
||||||
|
|
||||||
# はじめに
|
|
||||||
|
|
||||||
ビルドフェーズでは、解決しようとしている問題を表す量子プログラムを作成します。 量子プログラムの基本は、ゲート、測定、およびリセットを含む演算で構成される量子回路です。量子回路が量子コンピューター内の量子ビットを操作します。 回路は、要件に応じて Qiskit または OpenQASM を使って作成できます。
|
|
||||||
|
|
||||||
すべてのタスクでは 1 つ以上の[量子回路](circuit-construction)を作成する必要があります。 いくつかのタスクでは、さらに[量子演算子](operators-overview)を構築して、推定または測定する量子状態のプロパティを定義する必要もあります。
|
|
||||||
|
|
||||||
Qiskit では、抽象、仮想、物理、スケジュール、およびパルスプログラムという様々な抽象レベルで回路(およびある程度、演算子)を操作することができます。 最も抽象的なレベルは[回路ライブラリー](circuit-library)のタスク指向レンズです。 演算は、演算子、等値関数、および古典/ブール関数を使った抽象的な数学で、演算を表現することもできます。 仮想回路の場合、数学的抽象化は具体的なゲートセットの観点で具象表現を帯びます。 物理レベルでは、それらの命令は特定の物理量子ビットにマッピングされ、命令はターゲットハードウェアプラットフォームの接続性とネイティブゲートセットを反映するように書き直されます。 スケジュール回路はタイミング情報を導入し、[パルスプログラム](pulse)はチャンネル上の信号を表します。
|
|
||||||
|
|
||||||
Qiskit と [OpenQASM](introduction-to-qasm) は、古典値に対するリアルタイム計算を含めるように、許容される演算のセットを拡張する拡張回路の概念をさらにサポートしています。 このより豊富な回路ファミリーを操作するための Qiskit のツールは、[古典的なフィードフォワードと制御フロー](classical-feedforward-and-control-flow)に関するセクションにあります。
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [回路ライブラリー](circuit-library)のトピックを詳しく読み、回路を構築し始めます。
|
|
||||||
- [Grover's Algorithm(グローバーのアルゴリズム)](https://learning.quantum.ibm.com/tutorial/grovers-algorithm)チュートリアルで、回路の使用例をご覧ください。
|
|
||||||
- [Explore gates and circuits with the Quantum Composer(Quantum Composer によるゲートと回路の探索)](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer)チュートリアルで、単純な回路を操作します。
|
|
||||||
</Admonition>
|
|
|
@ -1,146 +0,0 @@
|
||||||
---
|
|
||||||
title: OpenQASM 2 と Qiskit
|
|
||||||
description: OpenQASM 2 と Qiskit 間でのコード変換
|
|
||||||
---
|
|
||||||
|
|
||||||
# OpenQASM 2 と Qiskit
|
|
||||||
|
|
||||||
Qiskit には、量子プログラムの OpenQASM 表現と [QuantumCircuit](../api/qiskit/qiskit.circuit.QuantumCircuit) クラスを変換するためのツールが備わっています。
|
|
||||||
|
|
||||||
## Qiskit への OpenQASM 2 プログラムのインポート
|
|
||||||
|
|
||||||
現在、OpenQASM 2 から Qiskit にインポートするために使用できる高レベル関数には 2 つあります。 ファイル名を取る `qasm2.load()` 関数と、プログラム自体を文字列として取る `qasm2.loads()` 関数です。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit.qasm2
|
|
||||||
qiskit.qasm2.load(filename, *, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)
|
|
||||||
```
|
|
||||||
|
|
||||||
詳細については、[OpenQASM 2 Qiskit API](/api/qiskit/qasm2) をご覧ください。
|
|
||||||
|
|
||||||
### 例: OpenQASM 2 プログラムを文字列としてインポートする
|
|
||||||
|
|
||||||
`qasm2.loads()` を使用して、OpenQASM 2 プログラムを文字列として QuantumCircuit にインポートします。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit.qasm2
|
|
||||||
program = '''
|
|
||||||
OPENQASM 2.0;
|
|
||||||
include "qelib1.inc";
|
|
||||||
qreg q[2];
|
|
||||||
creg c[2];
|
|
||||||
|
|
||||||
h q[0];
|
|
||||||
cx q[0], q[1];
|
|
||||||
|
|
||||||
measure q -> c;
|
|
||||||
'''
|
|
||||||
circuit = qiskit.qasm2.loads(program)
|
|
||||||
circuit.draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
![出力](/images/build/qasm2.png)
|
|
||||||
|
|
||||||
### 例: OpenQASM 2 プログラムをファイルからインポートする
|
|
||||||
|
|
||||||
`load()` を使用して、OpenQASM 2 プログラムをファイルから QuantumCircuit にインポートします。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit.qasm2
|
|
||||||
circuit = qiskit.qasm2.load("myfile.qasm")
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="custom-instructions"></span>
|
|
||||||
## カスタム量子命令
|
|
||||||
|
|
||||||
カスタム命令に関する情報の反復可能なオブジェクトを引数 `custom_instructions` として渡すことで、OpenQASM 2 言語の量子コンポーネントを拡張できます。 これらの命令に互換可能な定義があるファイルでは、指定されたコンストラクターが、他の処理している `qiskit.qasm2` が使用される場所に使用されます。 解析されたプログラムで定義された命令とは異なるパラメーター数や量子ビット数を持つカスタム命令は指定できません。 引数の反復可能オブジェクトの各要素は、以下のように、特定のデータクラスである必要があります。
|
|
||||||
|
|
||||||
#### `qiskit.qasm2.CustomInstruction(name, num_params, num_qubits, constructor, builtin=False)`
|
|
||||||
|
|
||||||
CustomInstruction クラスは、解析中に定義する必要のあるカスタム命令に関する情報を指定します。
|
|
||||||
|
|
||||||
`constructor` フィールドはシグネチャー `*args -> Instruction` を持つ呼び出し可能なオブジェクトであり、各 `num_params` args は浮動小数点値です。 ほとんどの組み込みの Qiskit ゲートクラスはこの形式です。
|
|
||||||
|
|
||||||
`builtin` フィールドはオプションです。 `true` にセットすると、インクルードされた OpenQASM 2 ファイルに定義がない場合でも、構文解析内で命令が定義されて使用可能になります。 `builtin` としてマークされた命令は、不透明またはゲート宣言を必要としませんが、互換可能な宣言をサイレントに無視します。
|
|
||||||
|
|
||||||
### 例: カスタム量子命令を使用する
|
|
||||||
|
|
||||||
`qasm2.loads()` を使用して、OpenQASM 2 プログラムを文字列として QuantumCircuit にインポートしますが、カスタム量子命令を使用します。 インポート元が指定された命令に対して出力するゲートオブジェクトに影響を与えたい場合があります。 `include "qelib1.inc"` 文で定義されるゲートは、適切な Qiskit circuit-library ゲートに自動的に関連付けられますが、これを閣僚することができます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit import Gate
|
|
||||||
from qiskit import qasm2
|
|
||||||
|
|
||||||
class MyGate(Gate):
|
|
||||||
def __init__(self, theta):
|
|
||||||
super().__init__("my", 2, [theta])
|
|
||||||
|
|
||||||
class Builtin(Gate):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__("builtin", 1, [])
|
|
||||||
|
|
||||||
program = '''
|
|
||||||
opaque my(theta) q1, q2;
|
|
||||||
qreg q[2];
|
|
||||||
my(0.5) q[0], q[1];
|
|
||||||
builtin q[0];
|
|
||||||
'''
|
|
||||||
customs = [
|
|
||||||
qasm2.CustomInstruction(name="my", num_params=1, num_qubits=2, constructor=MyGate),
|
|
||||||
# 'builtin=True' にセットすると、命令は宣言が使用可能であることを要求しません。
|
|
||||||
qasm2.CustomInstruction("builtin", 0, 1, Builtin, builtin=True),
|
|
||||||
]
|
|
||||||
circuit = qasm2.loads(program, custom_instructions=customs)
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="custom-classical"></span>
|
|
||||||
## カスタム古典関数
|
|
||||||
|
|
||||||
反復可能なオブジェクトを引数 `custom_classical` に渡すことで、古典式(引数からゲート)に行われた処理を拡張することができます。 これには、名前(有効な OpenQASM 2 識別子)、使用するパラメーター数(num_params)、および関数を実装する Python コーラブルが必要です。 Python コーラブルは `num_params` の位置浮動小数点引数を受け入れられる必要があり、浮動小数点または整数(浮動小数点に変換されます)を返す必要があります。 組み込み関数はオーバーライドできません。
|
|
||||||
|
|
||||||
#### `qiskit.qasm2.CustomClassical`
|
|
||||||
|
|
||||||
`CustomClassical` クラスは、数式で定義されるカスタム古典関数に関する情報を提供します。
|
|
||||||
|
|
||||||
指定された `callable` は、`num_params` の浮動小数点数を取り、浮動小数点数を返す Python 関数である必要があります。 `name` は OpenQASM 2 プログラムでそれを参照する識別子です。 これは定義済みのゲートと競合できません。
|
|
||||||
|
|
||||||
### 例: カスタム古典命令を使用する
|
|
||||||
|
|
||||||
`qasm2.loads()` を使用して、OpenQASM 2 プログラムを文字列として QuantumCircuit にインポートしますが、カスタム古典命令を使用します。 ゲートへの引数の記述中に使用される新しい古典関数を、プログラムの本体(定数畳み込み)と定義されたゲートのボディ(オンデマンドで計算)の両方に追加できます。 ここでは、Python バージョンの `atan2(y, x)` を指定します。これは数学的には $\\atan(y/x)$ ですが、角度の象限と無限大、およびカスタム `add_one` 関数を正しく処理します。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import math
|
|
||||||
import qiskit.qasm2
|
|
||||||
|
|
||||||
program = '''
|
|
||||||
include "qelib1.inc";
|
|
||||||
qreg q[2];
|
|
||||||
rx(atan2(pi, 3 + add_one(0.2))) q[0];
|
|
||||||
cx q[0], q[1];
|
|
||||||
'''
|
|
||||||
|
|
||||||
def add_one(x):
|
|
||||||
return x + 1
|
|
||||||
|
|
||||||
customs = [
|
|
||||||
# `atan2` は 2 つのパラメーターを取り、`math.atan2` はそれを実装します。
|
|
||||||
qasm2.CustomClassical("atan2", 2, math.atan2),
|
|
||||||
# `add_one` はパラメーターを 1 つしか取りません。
|
|
||||||
qasm2.CustomClassical("add_one", 1, add_one),
|
|
||||||
]
|
|
||||||
circuit = qasm2.loads(program, custom_classical=customs)
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="strict"></span>
|
|
||||||
## 厳格モード
|
|
||||||
|
|
||||||
デフォルトでは、このパーサーは公式の仕様よりも若干リラックスされています。 エラーが発生することなく、パラメーターリストでの末尾のコンマの使用、不要な(空ステートメント)セミコロンの使用、`OPENQASM 2.0;` バージョンステートメントの省略が可能である他、いくつかの QoL 改善も含まれています。 ただし、`strict=True` を使って "仕様書" モードを使用することができます。
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Explore gates and circuits with the Quantum Composer(Quantum Composer によるゲートと回路の探索)](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer)チュートリアルで、OpenQASM コードを生成する方法を学習します。
|
|
||||||
- [OpenQASM 2 Qiskit API](/api/qiskit/qasm2) リファレンスをご覧ください。
|
|
||||||
- [プログラムの検証](../verify/)のトピックをご覧ください。
|
|
||||||
- [OpenQASM Live Specification(OpenQASM の公開仕様)](https://openqasm.com/)にアクセスしてください。
|
|
||||||
</Admonition>
|
|
|
@ -1,132 +0,0 @@
|
||||||
---
|
|
||||||
title: OpenQASM 3 と Qiskit
|
|
||||||
description: OpenQASM 3 と Qiskit 間でのコード変換
|
|
||||||
---
|
|
||||||
|
|
||||||
# OpenQASM 3 と Qiskit
|
|
||||||
|
|
||||||
Qiskit には、量子プログラムの OpenQASM 表現と QuantumCircuit クラスを変換するためのツールが備わっています。 これらのツールは開発の探索フェーズにあり、OpenQASM 3 で表現される動的回路機能に対する Qiskit のサポートが高まるにつれて進化し続ける予定であることに注意してください。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
この関数はまだ探索段階にあります。 したがって、構文と機能が今後変化する可能性があります。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Qiskit への OpenQASM 3 プログラムのインポート
|
|
||||||
|
|
||||||
この関数を使用するには、パッケージ `qiskit_qasm3_import ` をインストールする必要があります。 以下のコマンドを使ってインストールします。
|
|
||||||
|
|
||||||
```python
|
|
||||||
pip install qiskit-qasm3-import
|
|
||||||
```
|
|
||||||
|
|
||||||
現在、OpenQASM 3 から Qiskit にインポートするために使用できる高レベル関数には 2 つあります。 ファイル名を取る `load()` 関数と、プログラム自体を文字列として取る `loads()` 関数です。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit.qasm3
|
|
||||||
qiskit.qasm3.load(file_name)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit.qasm3
|
|
||||||
qiskit.qasm3.loads(program-string)
|
|
||||||
```
|
|
||||||
|
|
||||||
この例では、OpenQASM 3 を使って量子プログラムを定義し、`loads()` を使って直接これを QuantumCircuit に変換しています。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit.qasm3
|
|
||||||
|
|
||||||
program = """
|
|
||||||
OPENQASM 3.0;
|
|
||||||
include "stdgates.inc";
|
|
||||||
|
|
||||||
input float[64] a;
|
|
||||||
qubit[3] q;
|
|
||||||
bit[2] mid;
|
|
||||||
bit[3] out;
|
|
||||||
|
|
||||||
let aliased = q[0:1];
|
|
||||||
|
|
||||||
gate my_gate(a) c, t {
|
|
||||||
gphase(a / 2);
|
|
||||||
ry(a) c;
|
|
||||||
cx c, t;
|
|
||||||
}
|
|
||||||
gate my_phase(a) c {
|
|
||||||
ctrl @ inv @ gphase(a) c;
|
|
||||||
}
|
|
||||||
|
|
||||||
my_gate(a * 2) aliased[0], q[{1, 2}][0];
|
|
||||||
measure q[0] -> mid[0];
|
|
||||||
measure q[1] -> mid[1];
|
|
||||||
|
|
||||||
while (mid == "00") {
|
|
||||||
reset q[0];
|
|
||||||
reset q[1];
|
|
||||||
my_gate(a) q[0], q[1];
|
|
||||||
my_phase(a - pi/2) q[1];
|
|
||||||
mid[0] = measure q[0];
|
|
||||||
mid[1] = measure q[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mid[0]) {
|
|
||||||
let inner_alias = q[{0, 1}];
|
|
||||||
reset inner_alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
out = measure q;
|
|
||||||
"""
|
|
||||||
circuit = qiskit.qasm3.loads(program)
|
|
||||||
circuit.draw("mpl")
|
|
||||||
```
|
|
||||||
|
|
||||||
![出力](/images/build/interoperate-qiskit-qasm3/qasm3circ.png)
|
|
||||||
|
|
||||||
## OpenQASM 3 へのエクスポート
|
|
||||||
|
|
||||||
文字列にエクスポートする `dumps()` またはファイルにエクスポートする `dump()` を使用して、Qiskit コードを OpenQASM 3 にエクスポートできます。
|
|
||||||
|
|
||||||
### `dumps()` の使用例
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.qasm3 import dumps
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.h(0)
|
|
||||||
qc.cx(0,1)
|
|
||||||
qc.measure_all()
|
|
||||||
|
|
||||||
dumps(qc)
|
|
||||||
```
|
|
||||||
|
|
||||||
出力:
|
|
||||||
|
|
||||||
`'OPENQASM 3;\ninclude "stdgates.inc";\nbit[2] meas;\nqubit[2] q;\nh q[0];\ncx q[0], q[1];\nbarrier q[0], q[1];\nmeas[0] = measure q[0];\nmeas[1] = measure q[1];\n'`
|
|
||||||
|
|
||||||
### `dump()` の使用例
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.qasm3 import dump
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.h(0)
|
|
||||||
qc.cx(0,1)
|
|
||||||
qc.measure_all()
|
|
||||||
|
|
||||||
f = open("my_file.txt", 'w')
|
|
||||||
dump(qc, f)
|
|
||||||
f.close()
|
|
||||||
```
|
|
||||||
|
|
||||||
詳細については、API リファレンスの [OpenQASM 3 へのエクスポート](/api/qiskit/qasm3#exporting-to-openqasm-3)のセクションをご覧ください。
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Explore gates and circuits with the Quantum Composer(Quantum Composer によるゲートと回路の探索)](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer)チュートリアルで、OpenQASM コードを生成する方法を学習します。
|
|
||||||
- [OpenQASM 3 Qiskit API](/api/qiskit/qasm3) リファレンスをご覧ください。
|
|
||||||
- [プログラムの検証](../verify/)のトピックをご覧ください。
|
|
||||||
- [OpenQASM Live Specification(OpenQASM の公開仕様)](https://openqasm.com/)をご覧ください。
|
|
||||||
</Admonition>
|
|
|
@ -1,52 +0,0 @@
|
||||||
---
|
|
||||||
title: OpenQASM の導入
|
|
||||||
description: OpenQASM(オープンな量子アセンブリ言語)の導入
|
|
||||||
---
|
|
||||||
|
|
||||||
# OpenQASM の導入
|
|
||||||
|
|
||||||
OpenQASM(オープンな量子アセンブリ言語)は、IBM 量子システムと互換性のある、マシンに依存しないプログラミングインターフェースであり、量子回路を記述するための命令型プログラミング言語です。 OpenQASM は量子回路モデルを使用して、量子プログラムをパラメーター化された演算(ゲート、測定、リセットなど)とリアルタイムの古典的計算の順序付きシーケンスとして表現します。 OpenQASM は、量子アルゴリズムのほかに、量子系の特徴づけ、検証、またはデバッグを意図した回路を記述することができます。
|
|
||||||
|
|
||||||
量子系の開発のニーズが進化するにつれ、OpenQASM の機能リストも拡大し、最新バージョンである [OpenQASM 3](https://arxiv.org/abs/2104.14722) には、古典的フィードフォワードフロー制御、ゲート修飾子、パルス実装などの拡張機能が組み込まれています。
|
|
||||||
|
|
||||||
OpenQASM はその多用途性により、様々なオーディエンスの選択肢となっています。 OpenQASM 3 論文[^1] の序文には、以下のような例があります。
|
|
||||||
|
|
||||||
> 「OpenQASM は高水準言語ではないが、多くのユーザーは表現力のあるドメイン固有言語を用いて単純な量子回路を手で書きたいと考えている。 回路のコンパイルを研究する研究者は、最適化と合成アルゴリズムに情報を渡すために、中間表現に記録された上位情報を必要としている。 実験者は、比較的高いレベルで回路を書く利便性を好むが、多くの場合、回路のあらゆる箇所で、タイミングまたはパルスレベルゲートの記述を手動で変更する必要がある。 古典的なコントローラーと波形ジェネレーターをデザインするハードウェアエンジニアは、ハードウェアの制約を考慮してコンパイルし、コントローラーが利用できる明示的な回路構造を作成できる実用的な言語を好む。」
|
|
||||||
|
|
||||||
OpenQASM は、独立した量子ソフトウェアツールの間で共通する交換フォーマットです。 回路を構築するためのツール、トランスパイル用の別のツール、などのようにさ様々なツールの使用を好む開発者にとって、OpenQASM はそれらのツールの橋渡しとして機能する_リンガフランカ_なのです。
|
|
||||||
|
|
||||||
Qiskit には、OpenQASM と [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) クラスの間で変換する方法が備わっています([OpenQASM 2 と Qiskit](interoperate-qiskit-qasm2) および [OpenQASM 3 と Qiskit](interoperate-qiskit-qasm3) をご覧ください)。
|
|
||||||
|
|
||||||
詳細については、[OpenQASM Live Specification(OpenQASM の公開仕様)](https://openqasm.com/)をご覧ください
|
|
||||||
|
|
||||||
## OpenQASM コードの例: cat の状態
|
|
||||||
|
|
||||||
```qasm3
|
|
||||||
|
|
||||||
OPENQASM 3;
|
|
||||||
include "stdgates.inc";
|
|
||||||
|
|
||||||
const n = 3; // 量子ビットの数
|
|
||||||
qubit[n] q; // n 量子ビットのレジスター 'q'
|
|
||||||
bit[n] c; // 古典ビットのレジスター 'c'
|
|
||||||
|
|
||||||
h q[0]; // アダマール
|
|
||||||
for k in [0:n-1] {
|
|
||||||
cnot q[k], q[k+1]; // 制御量子ビット q[k] からターゲット量子ビット q[k+1] までの制御 NOT
|
|
||||||
}
|
|
||||||
|
|
||||||
c = measure q; // 量子レジスターを測定
|
|
||||||
```
|
|
||||||
|
|
||||||
[^1]: Andrew W. Cross et al. "OpenQASM 3: A broader and deeper quantum assembly language," _ACM Transactions on Quantum Computing_, Volume 3, Issue 3 (2022). https://doi.org/10.48550/arXiv.2104.14722
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
|
|
||||||
- [Explore gates and circuits with the Quantum Composer(Quantum Composer によるゲートと回路の探索)](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer)チュートリアルで、OpenQASM コードを生成する方法を学習します。
|
|
||||||
- [OpenQASM 3 の機能表](qasm-feature-table)をご覧ください。
|
|
||||||
- [OpenQASM 3 Qiskit API](/api/qiskit/qasm3) リファレンスをお読みください。
|
|
||||||
- [OpenQASM 2 Qiskit API](/api/qiskit/qasm2) リファレンスをお読みください。
|
|
||||||
- [OpenQASM Live Specification(OpenQASM の公開仕様)](https://openqasm.com/)にアクセスしてください。
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,78 +0,0 @@
|
||||||
---
|
|
||||||
title: OpenQASM 3 feature table
|
|
||||||
description: A list of the OpenQASM 3 language features
|
|
||||||
---
|
|
||||||
|
|
||||||
# OpenQASM 3 feature table
|
|
||||||
|
|
||||||
Below is a list of the `OpenQASM 3` language features.
|
|
||||||
|
|
||||||
For more details on these capabilities, see the [OpenQASM 3.X Live Specification](https://openqasm.com/) .
|
|
||||||
|
|
||||||
Key:
|
|
||||||
|
|
||||||
- ❌ Not supported
|
|
||||||
- 🟡 Partial support
|
|
||||||
- ✅ Supported
|
|
||||||
|
|
||||||
| Feature | Support | Comments |
|
|
||||||
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| comments | ✅ | |
|
|
||||||
| QASM version string | ✅ | |
|
|
||||||
| `include` | ✅ | |
|
|
||||||
| unicode names | ✅ | |
|
|
||||||
| `qubit` | 🟡 | Only supports physical qubits, and no arrays. |
|
|
||||||
| `bit` | ✅ | |
|
|
||||||
| `bool` | ✅ | |
|
|
||||||
| `int` | ✅ | Some support for comparisons against integers and casting. |
|
|
||||||
| `uint` | ❌ | |
|
|
||||||
| `float` | ❌ | |
|
|
||||||
| `angle` | ❌ | |
|
|
||||||
| `complex` | ❌ | |
|
|
||||||
| `const` | ❌ | |
|
|
||||||
| `pi`/`π`/`tau`/`τ`/`euler`/`ℇ` | ❌ | |
|
|
||||||
| Aliasing: let | ❌ | |
|
|
||||||
| register concatenation | ❌ | |
|
|
||||||
| casting | 🟡 | Casting between arrays of bits, int, and bool is supported |
|
|
||||||
| `duration` | ✅ | |
|
|
||||||
| `durationof` | ❌ | |
|
|
||||||
| `ns`/`µs`/`us`/`ms`/`s`/`dt` | ✅ | |
|
|
||||||
| `stretch` | ❌ | |
|
|
||||||
| `delay` | ✅ | |
|
|
||||||
| `barrier` | ✅ | |
|
|
||||||
| `box` | ❌ | |
|
|
||||||
| Built-in `U` | ✅ | |
|
|
||||||
| `gate` | ✅ | No support for non-basis gates |
|
|
||||||
| `gphase` | ❌ | |
|
|
||||||
| `ctrl @`/ `negctrl @` | ❌ | |
|
|
||||||
| `inv @` | ❌ | |
|
|
||||||
| `pow(k) @` | ❌ | |
|
|
||||||
| `reset` | ✅ | |
|
|
||||||
| `measure` | ✅ | |
|
|
||||||
| bit operations | ✅ | |
|
|
||||||
| boolean operations | ✅ | |
|
|
||||||
| arithmetic expressions | ❌ | |
|
|
||||||
| comparisons | ✅ | |
|
|
||||||
| `if` | ✅ | |
|
|
||||||
| `else` | ✅ | |
|
|
||||||
| `else if` | ❌ | |
|
|
||||||
| `for` loops | 🟡 | Discrete sets and negative stepping is not supported. |
|
|
||||||
| `while` loops | ❌ | |
|
|
||||||
| `continue` | ❌ | |
|
|
||||||
| `break` | ❌ | |
|
|
||||||
| `return` | ❌ | |
|
|
||||||
| `extern` | 🟡 | Only for certain extern subroutines exposed by systems. It is currently not possible for clients to submit these. |
|
|
||||||
| `def` subroutines (classical) | ❌ | |
|
|
||||||
| `def` subroutines (quantum) | ❌ | |
|
|
||||||
| `input` | ❌ | |
|
|
||||||
| `output` | ❌ | |
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Learn how to generate OpenQASM code in the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial.
|
|
||||||
- See the [OpenQASM 3 Qiskit API](/api/qiskit/qasm3) reference.
|
|
||||||
- See the [OpenQASM 2 Qiskit API](/api/qiskit/qasm2) reference.
|
|
||||||
- Review the [Verify your program](../verify/) topic.
|
|
||||||
- Visit the [OpenQASM Live Specification](https://openqasm.com/).
|
|
||||||
</Admonition>
|
|
|
@ -1,165 +0,0 @@
|
||||||
---
|
|
||||||
title: パウリ基底での観測量の指定
|
|
||||||
description: 様々なパウリ基底で回路を測定します。計算基底で対角線ではない観測量を測定するために必要です。
|
|
||||||
---
|
|
||||||
|
|
||||||
# パウリ基底での観測量の指定
|
|
||||||
|
|
||||||
量子力学では、観測量は測定可能な物理的特性に対応します。
|
|
||||||
例えば、スピンのシステムを考えた場合、システムのエネルギーの測定や、磁化やスピン間の相関関係など、スピンのアラインメントに関する情報の取得に関心を持つ場合があります。
|
|
||||||
|
|
||||||
量子コンピューターで $n$ 量子ビット観測量 $O$ を測定する場合、これを以下のようにパウリ演算子のテンソル積の合計として表す必要があります。
|
|
||||||
|
|
||||||
$$
|
|
||||||
O = \\sum\_{k=1}^K \\alpha_k P_k,~~ P_k \\in {I, X, Y, Z}^{\\otimes n},~~ \\alpha_k \\in \\mathbb{R},
|
|
||||||
$$
|
|
||||||
|
|
||||||
ここで、それぞれ以下を意味します。
|
|
||||||
|
|
||||||
$$
|
|
||||||
I = \\begin{pmatrix}
|
|
||||||
1 & 0 \\ 0 & 1
|
|
||||||
\\end{pmatrix}
|
|
||||||
~~
|
|
||||||
X = \\begin{pmatrix}
|
|
||||||
0 & 1 \\ 1 & 0
|
|
||||||
\\end{pmatrix}
|
|
||||||
~~
|
|
||||||
Y = \\begin{pmatrix}
|
|
||||||
0 & -i \\ i & 0
|
|
||||||
\\end{pmatrix}
|
|
||||||
~~
|
|
||||||
Z = \\begin{pmatrix}
|
|
||||||
1 & 0 \\ 0 & -1
|
|
||||||
\\end{pmatrix}
|
|
||||||
$$
|
|
||||||
|
|
||||||
そして、$O^\\dagger = O$ のように、観測量がエルミートであるという事実を使用します。 $O$ がエルミートでない場合でも、パウリの和として分解することはできますが、係数 $\\alpha_k$ が複雑になります。
|
|
||||||
|
|
||||||
多くの場合、観測量は、対象のシステムを量子ビットにマッピングした後に、この表現に自然に指定されます。
|
|
||||||
例えば、スピン 1/2 システムは、イジング・ハミルトニアンにマッピングできます。
|
|
||||||
|
|
||||||
$$
|
|
||||||
H = \\sum_{\\langle i, j\\rangle} Z_i Z_j - \\sum_{i=1}^n X_i,
|
|
||||||
$$
|
|
||||||
|
|
||||||
ここで、インデックス $\\langle i, j\\rangle$ は、相互に作用するスピンで実行され、スピンは $X$ の横磁場の影響を受けます。
|
|
||||||
添え字インデックスは、パウリ演算子が動作する量子ビットを示します。すなわち $X_i$ は量子ビット $i$ に $X$ 演算子を適用し、残りは変更されないままになります。
|
|
||||||
Qiskit では、このハミルトニアンは以下のように構築できます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
# 量子ビットの数を定義します
|
|
||||||
n = 12
|
|
||||||
|
|
||||||
# 単一パウリ項を ("Paulis", [インデックス], 係数) として定義します
|
|
||||||
interactions = [("ZZ", [i, i + 1], 1) for i in range(n - 1)] # we assume spins on a 1D line
|
|
||||||
field = [("X", [i], -1) for i in range(n)]
|
|
||||||
|
|
||||||
# 演算子を作成します
|
|
||||||
hamiltonian = SparsePauliOp.from_sparse_list(interactions + field, num_qubits=n)
|
|
||||||
```
|
|
||||||
|
|
||||||
エネルギーを測定する場合は、観測量がハミルトニアンそのものです。 または、$Z$ 方向に沿って
|
|
||||||
観測量に合わせてスピンの回数をカウントすることで、平均磁化などのシステム
|
|
||||||
プロパティを測定することに
|
|
||||||
関心があるかもしれません。
|
|
||||||
|
|
||||||
$$
|
|
||||||
O = \\frac{1}{n} \\sum\_{i=1} Z_i
|
|
||||||
$$
|
|
||||||
|
|
||||||
パウリ演算子ではなく行列で指定された観測量については、これらを量子コンピューターで評価するために、まずパウリ基底で再作成する必要があります。
|
|
||||||
パウリ行列はエルミート $2^n \\times 2^n$ 行列の基底を成すため、そのような表現をいつでも見つけることができます。
|
|
||||||
観測量 $O$ を以下のように展開します。
|
|
||||||
|
|
||||||
$$
|
|
||||||
O = \\sum\_{P \\in {I, X, Y, Z}^{\\otimes n}} \\mathrm{Tr}(O P) P,
|
|
||||||
$$
|
|
||||||
|
|
||||||
ここで、合計はすべての可能な $n$ 量子ビットパウリ項に渡って計算され、$\\mathrm{Tr}(\\cdot)$ は内積として機能する行列のトレースです。
|
|
||||||
この分解は、以下のように `SparsePauliOp.from_operator` メソッドを使用して、行列からパウリ項に実装できます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
matrix = np.array([[-1, 0, 0.5, -1],
|
|
||||||
[0, 1, 1, 0.5],
|
|
||||||
[0.5, 1, -1, 0],
|
|
||||||
[-1, 0.5, 0, 1]])
|
|
||||||
|
|
||||||
observable = SparsePauliOp.from_operator(matrix)
|
|
||||||
print(observable)
|
|
||||||
```
|
|
||||||
|
|
||||||
これは以下を出力します。
|
|
||||||
|
|
||||||
```
|
|
||||||
SparsePauliOp(['IZ', 'XI', 'YY'], coeffs=[-1. +0.j, 0.5+0.j, 1. +0.j])
|
|
||||||
```
|
|
||||||
|
|
||||||
つまり、行列はパウリ項として、$O = -Z_1 + 0.5 X_2 + Y_2 Y_1$ のように記述できるということです。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
テンソル積の順序は、$q_n \otimes q_{n-1} \otimes \cdots \otimes q_1$ として量子ビットにマッピングされていることを覚えておきましょう。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
観測量がエルミートである場合(つまり $O^\dagger = O$)、パウリ係数は実数です。
|
|
||||||
しかし、複素数値係数を使用できる場合、パウリに関してその他あらゆる複素行列を分解することもできます。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## パウリ基底の測定
|
|
||||||
|
|
||||||
測定は、量子状態を計算基底 ${|0\\rangle, |1\\rangle}$ に投影します。 これは、$I$ 項と $Z$ 項でのみ構成されるパウリなど、この基底で対角線である観測量のみを測定できることを意味します。
|
|
||||||
したがって、任意のパウリ項を測定するには、それらを対角化するための基底の変更が必要です。 これを行うには、以下の変換を実行します。
|
|
||||||
|
|
||||||
$$
|
|
||||||
\\begin{aligned}
|
|
||||||
X &\\rightarrow Z = H X H \\
|
|
||||||
Y &\\rightarrow Z = H S^\\dagger Y S H,
|
|
||||||
\\end{aligned}
|
|
||||||
$$
|
|
||||||
|
|
||||||
ここで、$H$ はアダマールゲートで、$S = \\sqrt{Z}$ は位相ゲートと呼ばれることがあります。
|
|
||||||
[Estimator](../api/qiskit/qiskit.primitives.Estimator) を使用して期待値を計算している場合、基底の変換が自動的に実行されます。
|
|
||||||
|
|
||||||
以下は、量子回路を用意し、X 基底で量子ビット 0、Y 基底で量子ビット 1、
|
|
||||||
Z 基底で量子ビット 2 を手動で測定する方法を
|
|
||||||
示した例です。
|
|
||||||
前の方程式で示した変換を適用し、以下の回路を取得します。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit import QuantumCircuit
|
|
||||||
|
|
||||||
# X 基底で q0、Y 基底で q1、Z 基底で q2 を測定
|
|
||||||
# する回路を作成します
|
|
||||||
circuit = QuantumCircuit(3)
|
|
||||||
circuit.ry(0.8, 0)
|
|
||||||
circuit.cx(0, 1)
|
|
||||||
circuit.cx(1, 2)
|
|
||||||
circuit.barrier()
|
|
||||||
|
|
||||||
# アダマールゲートで X を対角化します
|
|
||||||
circuit.h(0)
|
|
||||||
|
|
||||||
# アダマールを S^\dagger として Y を対角化します
|
|
||||||
circuit.h(1)
|
|
||||||
circuit.sdg(1)
|
|
||||||
|
|
||||||
# Z 基底はデフォルトであるため、ここではアクションは不要です
|
|
||||||
|
|
||||||
# measure all qubits
|
|
||||||
circuit.measure_all()
|
|
||||||
circuit.draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
![出力](/images/build/paulibasis.png)
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Variational quantum eigensolver(変分量子固有ソルバー)](https://learning.quantum.ibm.com/tutorial/variational-quantum-eigensolver)チュートリアルで回路分解の例をご覧ください。
|
|
||||||
- [SparsePauliOp API](/api/qiskit/qiskit.quantum_info.SparsePauliOp#sparsepauliop) リファレンスをお読みください。
|
|
||||||
</Admonition>
|
|
|
@ -1,66 +0,0 @@
|
||||||
---
|
|
||||||
title: Synthesize unitary operations
|
|
||||||
description: On the implementation of arbitrary unitary matrices on qubits
|
|
||||||
---
|
|
||||||
|
|
||||||
# Synthesize unitary operations
|
|
||||||
|
|
||||||
A unitary operation describes a norm-preserving change to a quantum system.
|
|
||||||
For $n$ qubits this change is described by a $2^n \\times 2^n$ dimensional, complex matrix $U$ whose adjoint equals the inverse, that is $U^\\dagger U = \\mathbb{1}$.
|
|
||||||
|
|
||||||
Synthesizing specific unitary operations into a set of quantum gates is a fundamental task used, for example, in the design and application of quantum algorithms or in compiling quantum circuits.
|
|
||||||
|
|
||||||
While efficient synthesis is possible for certain classes of unitaries – like those composed of Clifford gates or having a tensor product structure – most unitaries do not fall into these categories.
|
|
||||||
For general unitary matrices, synthesis is a complex task with computational costs that increase exponentially with the number of qubits.
|
|
||||||
Therefore, if you know an efficient decomposition for the unitary you would like to implement, it will likely be better than a general synthesis.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If no decomposition is available, Qiskit provides you with the tools to find one.
|
|
||||||
However, note that this generally generates deep circuits that may be unsuitable to run on noisy quantum computers.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
|
|
||||||
U = 0.5 * np.array([
|
|
||||||
[1, 1, 1, 1],
|
|
||||||
[-1, 1, -1, 1],
|
|
||||||
[-1, -1, 1, 1],
|
|
||||||
[-1, 1, 1, -1]
|
|
||||||
])
|
|
||||||
|
|
||||||
circuit = QuantumCircuit(2)
|
|
||||||
circuit.unitary(U, circuit.qubits)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Re-synthesis for circuit optimization
|
|
||||||
|
|
||||||
Sometimes it is beneficial to re-synthesize a long series of single- and two-qubit gates, if the length can be reduced. For example, the following circuit uses three two-qubit gates.
|
|
||||||
|
|
||||||
![output](/images/build/unitary-synthesis/unitary_target.png)
|
|
||||||
|
|
||||||
However, after re-synthesizing with the following code, it only needs a single CX gate.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.quantum_info import Operator
|
|
||||||
|
|
||||||
# compute unitary matrix of target_circuit
|
|
||||||
U = Operator(target_circuit)
|
|
||||||
|
|
||||||
# re-synthesize
|
|
||||||
better_circuit = QuantumCircuit(2)
|
|
||||||
better_circuit.unitary(U, range(2))
|
|
||||||
better_circuit.decompose().draw()
|
|
||||||
```
|
|
||||||
|
|
||||||
![output](/images/build/unitary-synthesis/unitary_resynth.png)
|
|
||||||
|
|
||||||
Qiskit's [transpile](../api/qiskit/compiler#qiskit.compiler.transpile) function automatically performs this re-synthesis for a sufficiently high optimization level.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- See an example of circuit decomposition in the [Grover's Algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.
|
|
||||||
- For more information about the Qiskit transpiler, visit the [Transpile section](../transpile/index).
|
|
||||||
</Admonition>
|
|
|
@ -1,136 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Run",
|
|
||||||
"collapsed": true,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Introduction",
|
|
||||||
"url": "/run"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Run with primitives",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Introduction to primitives",
|
|
||||||
"url": "/run/primitives"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Get started with primitives",
|
|
||||||
"url": "/run/primitives-get-started"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Primitives examples",
|
|
||||||
"url": "/run/primitives-examples"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Configure runtime options",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Configure runtime compilation",
|
|
||||||
"url": "/run/configure-runtime-compilation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Configure runtime error mitigation",
|
|
||||||
"url": "/run/configure-error-mitigation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Advanced runtime options",
|
|
||||||
"url": "/run/advanced-runtime-options"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Execution modes",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "About sessions",
|
|
||||||
"url": "/run/sessions"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Run jobs in a session",
|
|
||||||
"url": "/run/run-jobs-in-session"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Run jobs in a batch",
|
|
||||||
"url": "/run/run-jobs-batch"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Manage jobs",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Monitor a job",
|
|
||||||
"url": "/run/monitor-job"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Estimate job run time",
|
|
||||||
"url": "/run/estimate-job-run-time"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Minimize job run time",
|
|
||||||
"url": "/run/minimize-time"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Maximum execution time",
|
|
||||||
"url": "/run/max-execution-time"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Quantum Serverless workloads",
|
|
||||||
"url": "/run/quantum-serverless"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Hardware",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Processor types",
|
|
||||||
"url": "/run/processor-types"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "System information",
|
|
||||||
"url": "/run/system-information"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Get backend information with Qiskit",
|
|
||||||
"url": "/run/get-backend-information"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Native gates and operations",
|
|
||||||
"url": "/run/native-gates"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Retired systems",
|
|
||||||
"url": "/run/retired-systems"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Hardware considerations and limitations for classical feedforward and control flow",
|
|
||||||
"url": "/run/dynamic-circuits-considerations"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Understand the platform",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Instances",
|
|
||||||
"url": "/run/instances"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Fair-share queue",
|
|
||||||
"url": "/run/fair-share-queue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Manage cost",
|
|
||||||
"url": "/run/manage-cost"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Reserve system time",
|
|
||||||
"url": "/run/reserve-system-time"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,167 +0,0 @@
|
||||||
---
|
|
||||||
title: Advanced runtime options
|
|
||||||
description: Specify options when building with Qiskit runtime primitives
|
|
||||||
---
|
|
||||||
|
|
||||||
# Advanced Qiskit Runtime options
|
|
||||||
|
|
||||||
When calling the primitives, you can pass in options by using the `Options` class or when using the `run` method. In the `Options` class, commonly used options, such as `resilience_level`, are at the first level. Other options are grouped into different categories:
|
|
||||||
|
|
||||||
![The image shows the top-level options categories: transpilation, resilience, execution, environment, and simulation.](/images/build/options.png "Option categories")
|
|
||||||
|
|
||||||
<Admonition type="info" title="Attention">
|
|
||||||
This section focuses on Qiskit Runtime primitive [Options](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.Options) (imported from `qiskit_ibm_runtime`). While most of the `primitives` interface is common across implementations, most `Options` are not. Consult the
|
|
||||||
corresponding API references for information about the `qiskit.primitives` and `qiskit_aer.primitives` options.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Instantiate the Options class
|
|
||||||
|
|
||||||
In the example below, we create an instance of the `Options` class. `optimization_level` is a first-level option and can be passed as an input parameter. Options related to the execution environment are passed using the `environment` parameter.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Options
|
|
||||||
|
|
||||||
options = Options(optimization_level=3, environment={"log_level": "INFO"})
|
|
||||||
```
|
|
||||||
|
|
||||||
The `Options` class supports auto-complete. Once you create an instance of the `Options` class, you can use auto-complete to see what options are available. If you choose one of the categories, you can use auto-complete again to see what options are available under that category.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Options
|
|
||||||
|
|
||||||
options = Options()
|
|
||||||
options.resilience_level = 1
|
|
||||||
options.execution.shots = 2048
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pass options to a primitive
|
|
||||||
|
|
||||||
### Options class
|
|
||||||
|
|
||||||
When creating an instance of the `Estimator` or `Sampler` class, you can pass in the `options` you just created. Those options will then be applied when you use `run()` to perform the calculation. Example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
estimator = Estimator(session=backend, options=options)
|
|
||||||
result = estimator.run(circuit, observable).result()
|
|
||||||
print(f">>> Metadata: {result.metadata[0]}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run() method
|
|
||||||
|
|
||||||
You can pass in options by using the `run()` method. This overwrites the options you specified when creating the `Estimator` or `Sampler` instance for that particular execution.
|
|
||||||
|
|
||||||
Because most users will only overwrite a few options at the job level, it is not necessary to specify the category the options are in. The code below, for example, specifies `shots=1024` instead of `execution={"shots": 1024}` (which is also valid).
|
|
||||||
|
|
||||||
```python
|
|
||||||
estimator = Estimator(session=backend, options=options)
|
|
||||||
result = estimator.run(circuit, observable, shots=1024).result()
|
|
||||||
print(f">>> Metadata: {result.metadata[0]}")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commonly used options
|
|
||||||
|
|
||||||
There are many available options, but the following are the most commonly used:
|
|
||||||
|
|
||||||
### Shots
|
|
||||||
|
|
||||||
For some algorithms, setting a specific number of shots is a core part of their routines. Previously, shots could be set during the call to `backend.run()`. For example, `backend.run(shots=1024)`. Now, that setting is part of the execution
|
|
||||||
options ("second level option"). This can be done during the primitive setup:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Estimator, Options
|
|
||||||
|
|
||||||
options = Options()
|
|
||||||
options.execution.shots = 1024
|
|
||||||
|
|
||||||
estimator = Estimator(session=backend, options=options)
|
|
||||||
```
|
|
||||||
|
|
||||||
If you need to modify the number of shots set between iterations (primitive calls), you can set the
|
|
||||||
shots directly in the `run()` method. This overwrites the initial `shots` setting.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Estimator
|
|
||||||
|
|
||||||
estimator = Estimator(session=backend)
|
|
||||||
|
|
||||||
estimator.run(circuits=circuits, observables=observables, shots=50)
|
|
||||||
|
|
||||||
# other logic
|
|
||||||
|
|
||||||
estimator.run(circuits=circuits, observables=observables, shots=100)
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information about the primitive options, refer to the
|
|
||||||
[Options class API reference](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.Options).
|
|
||||||
|
|
||||||
### Runtime compilation
|
|
||||||
|
|
||||||
The Qiskit Runtime primitives expect to be called with circuits already suitable for execution on the target system. This implies that the user has already transpiled their circuits to respect the native gate set and connectivity constraints of the target system.
|
|
||||||
|
|
||||||
The Qiskit Runtime primitives may perform additional runtime compilation to optimize circuits, with the degree of optimization controlled by an optimization level option. The optimization level you choose affects the compilation strategy, with higher levels invoking more expensive or aggressive optimizations.
|
|
||||||
|
|
||||||
See the Optimization level table in the
|
|
||||||
[Runtime compilation topic](configure-runtime-compilation#set-the-optimization-level) for further details.
|
|
||||||
|
|
||||||
<Admonition>
|
|
||||||
In the currently deployed Qiskit Runtime primitives, optimization levels 2 and 3 behave identically to level 1. If you want to use more advanced optimization, use the Qiskit transpiler locally, set [`skip_transpilation=True`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.TranspilationOptions#skip_transpilation), and then pass the transpiled circuits to the primitives. For instructions see the [Submit pre-transpiled circuits](https://learning.quantum.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives) tutorial.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
The optimization level option is a "first-level option", and can be set as follows:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Estimator, Options
|
|
||||||
|
|
||||||
options = Options(optimization_level=1)
|
|
||||||
|
|
||||||
# or..
|
|
||||||
options = Options()
|
|
||||||
options.optimization_level = 1
|
|
||||||
|
|
||||||
estimator = Estimator(session=backend, options=options)
|
|
||||||
```
|
|
||||||
|
|
||||||
Turning off all optional runtime compilation steps requires a "second-level option", as follows:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Estimator, Options
|
|
||||||
|
|
||||||
options = Options()
|
|
||||||
options.transpilation.skip_transpilation = True
|
|
||||||
|
|
||||||
estimator = Estimator(session=backend, options=options)
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information and a complete list of advanced transpilation options, see the Advanced transpilation options table in the
|
|
||||||
[Runtime compilation topic](configure-runtime-compilation#transpilation-table).
|
|
||||||
|
|
||||||
### Error mitigation
|
|
||||||
|
|
||||||
You might want to leverage different error mitigation methods and see how these affect the performance of your
|
|
||||||
algorithm. These can also be set through the `resilience_level` option. The method selected for each level is
|
|
||||||
different for `Sampler` and `Estimator`. You can find more information in the
|
|
||||||
[Configure error mitigation topic](configure-error-mitigation).
|
|
||||||
|
|
||||||
The configuration is similar to the other options:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Estimator, Options
|
|
||||||
|
|
||||||
options = Options(resilience_level = 2)
|
|
||||||
|
|
||||||
# or...
|
|
||||||
|
|
||||||
options = Options()
|
|
||||||
options.resilience_level = 2
|
|
||||||
|
|
||||||
estimator = Estimator(session=backend, options=options)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Find more details about the `Estimator` methods in the [Estimator API reference](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.Estimator#estimator).
|
|
||||||
- Find more details about the `Sampler` methods in the [Sampler API reference](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.Sampler#sampler).
|
|
||||||
- Find all available options in the [Options API reference](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.Options).
|
|
||||||
- Find details about [runtime compilation](../run/configure-runtime-compilation) and [error mitigation](../run/configure-error-mitigation).
|
|
||||||
</Admonition>
|
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
title: System circuit execution
|
|
||||||
description: Explanatory content on fixed and dynamic repetition rate execution
|
|
||||||
---
|
|
||||||
|
|
||||||
# System circuit execution
|
|
||||||
|
|
||||||
## Fixed repetition rate execution
|
|
||||||
|
|
||||||
Most IBM Quantum systems execute circuits at a fixed rate. Although this _repetition rate_ varies by system, the underlying execution model is the same, and is described here. First, consider three circuits sent to a system using separate jobs, one for each circuit. The example below shows what happens for jobs of varying lengths. Because of the fixed repetition rate, there is a variable amount of _idle time_ that occurs before the start of a circuit in order to make the entire duration match that given by the system repetition rate.
|
|
||||||
|
|
||||||
![With fixed-rate execution, shorter jobs result in longer idle time.](/images/run/fixed_single_circuit1.png "Idle time versus job length")
|
|
||||||
|
|
||||||
The situation changes somewhat when the same circuits are batched into a single job. In this case the circuits included in the job are executed by iterating over the circuits for each shot requested; the execution is column-wise over a matrix of circuits and shots (see below).
|
|
||||||
|
|
||||||
![The first column represents shot0. The circuits are run in order from 0 through 3. The second column represents shot 1. The circuits are run in order from 0 through 3. The remaining columns follow the same pattern. ](/images/run/circuits_shots_matrix1.png "Column-wise execution matrix")
|
|
||||||
|
|
||||||
Matrix of four circuits in a job showing the execution pattern over the circuits.
|
|
||||||
|
|
||||||
When submitting batches of circuits to the systems, the circuits are executed differently than they would be if executed separately. Namely, the initialization of the circuit, that is, prepare the ground state, and measurements (if any) are aligned over all circuits.
|
|
||||||
|
|
||||||
![The image shows three circuits. Although they are different lengths, they take the same amount of time to complete because they were submitted in a batch.](/images/run/fixed_batch_circuit1.png)
|
|
||||||
|
|
||||||
Therefore, each circuit is equal in duration to the longest circuit in the batch, and there is a common idle time that is placed in front of all circuits to match the repetition rate.
|
|
||||||
|
|
||||||
## Dynamic repetition rate execution
|
|
||||||
|
|
||||||
Some IBM Quantum systems allow for dynamic repetition rate execution. These systems are identified in Qiskit using `backend.configuration().dynamic_reprate_enabled`, and return a value of `True`. On these systems, it is possible to manually set the above idle time by setting the `rep_delay` of the submitted job. One can see from the above figures that by reducing the idle time one can potentially see a greater throughput of circuits on the systems that support dynamic repetition rates. See the the next section on conditional reset for more detailed usage examples.
|
|
|
@ -1,307 +0,0 @@
|
||||||
---
|
|
||||||
title: Configure error mitigation
|
|
||||||
description: Configure error mitigation with Qiskit Runtime
|
|
||||||
---
|
|
||||||
|
|
||||||
# Configure error mitigation for Qiskit Runtime
|
|
||||||
|
|
||||||
Error mitigation techniques allow users to mitigate circuit errors by
|
|
||||||
modeling the device noise at the time of execution. This typically
|
|
||||||
results in quantum pre-processing overhead related to model training and
|
|
||||||
classical post-processing overhead to mitigate errors in the raw results
|
|
||||||
by using the generated model.
|
|
||||||
|
|
||||||
The error mitigation techniques built in to primitives are advanced
|
|
||||||
resilience options. To specify these options, use the `resilience_level`
|
|
||||||
option when submitting your job.
|
|
||||||
|
|
||||||
The resilience level specifies how much resilience to build against
|
|
||||||
errors. Higher levels generate more accurate results, at the expense of
|
|
||||||
longer processing times. Resilience levels can be used to configure the
|
|
||||||
cost/accuracy trade-off when applying error mitigation to your primitive
|
|
||||||
query. Error mitigation reduces errors (bias) in results by processing
|
|
||||||
the outputs from a collection, or ensemble, of related circuits. The
|
|
||||||
degree of error reduction depends on the method applied. The resilience
|
|
||||||
level abstracts the detailed choice of error mitigation method to allow
|
|
||||||
users to reason about the cost/accuracy trade that is appropriate to
|
|
||||||
their application.
|
|
||||||
|
|
||||||
Given this, each level corresponds to a method or methods with
|
|
||||||
increasing level of quantum sampling overhead to enable you experiment
|
|
||||||
with different time-accuracy tradeoffs. The following table shows you
|
|
||||||
which levels and corresponding methods are available for each of the
|
|
||||||
primitives.
|
|
||||||
|
|
||||||
<Admonition type="info" title="Attention">
|
|
||||||
Error mitigation is task specific so the techniques you are able to
|
|
||||||
apply vary based whether you are sampling a distribution or generating
|
|
||||||
expectation values.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
| Resilience Level | Definition | Estimator | Sampler |
|
|
||||||
| ---------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------- |
|
|
||||||
| 0 | No mitigation | None | None |
|
|
||||||
| 1 [Default] | Minimal mitigation costs: Mitigate error associated with readout errors | Twirled Readout Error eXtinction (TREX) | Matrix-free Measurement Mitigation (M3) |
|
|
||||||
| 2 | Medium mitigation costs. Typically reduces bias in estimators, but is not guaranteed to be zero-bias. | Zero Noise Extrapolation (ZNE) | - |
|
|
||||||
| 3 | Heavy mitigation with layer sampling. Theoretically expected to deliver zero-bias estimators. | Probabilistic Error Cancellation (PEC) | - |
|
|
||||||
|
|
||||||
<Admonition type="info" title="Attention">
|
|
||||||
|
|
||||||
Resilience levels are currently in beta so sampling overhead and
|
|
||||||
solution quality will vary from circuit to circuit. New features,
|
|
||||||
advanced options, and management tools will be released on a rolling
|
|
||||||
basis. Specific error mitigation methods are not guaranteed to be
|
|
||||||
applied at each resilience level.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If using an IBM Cloud Qiskit Runtime service instance with Q-CTRL performance management enabled, there is no need to specify runtime optimization or resilience levels, as the strategy includes an automatic preset.
|
|
||||||
|
|
||||||
Setting `optimization_level` or `resilience_level` equal to 0 will result in an
|
|
||||||
execution error. Levels 1, 2, and 3 are permitted but will not impact performance.
|
|
||||||
Setting other options will likewise not impact performance, and it may result in a
|
|
||||||
runtime warning. For more information visit the [Q-CTRL documentation](https://docs.q-ctrl.com/q-ctrl-embedded).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Configure the Estimator with resilience levels
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Resilience Level 0</summary>
|
|
||||||
|
|
||||||
No error mitigation is applied to the user program.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Resilience Level 1</summary>
|
|
||||||
|
|
||||||
Level 1 applies error mitigation methods that particularly address
|
|
||||||
readout errors. In the Estimator, we apply a model-free technique known
|
|
||||||
as Twirled Readout Error eXtinction (TREX). It reduces measurement error
|
|
||||||
by diagonalizing the noise channel associated with measurement by
|
|
||||||
randomly flipping qubits through X gates immediately before measurement,
|
|
||||||
and flipping the corresponding measured bit if an X gate was applied. A
|
|
||||||
rescaling term from the diagonal noise channel is learned by
|
|
||||||
benchmarking random circuits initialized in the zero state. This allows
|
|
||||||
the service to remove bias from expectation values that result from
|
|
||||||
readout noise. This approach is described further in [Model-free
|
|
||||||
readout-error mitigation for quantum expectation
|
|
||||||
values](https://arxiv.org/abs/2012.09738).
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Resilience Level 2</summary>
|
|
||||||
|
|
||||||
Level 2 uses the Zero Noise Extrapolation method (ZNE) which computes an
|
|
||||||
expectation value of the observable for different noise factors
|
|
||||||
(amplification stage) and then uses the measured expectation values to
|
|
||||||
infer the ideal expectation value at the zero-noise limit (extrapolation
|
|
||||||
stage). This approach tends to reduce errors in expectation values, but
|
|
||||||
is not guaranteed to produce an unbiased result.
|
|
||||||
|
|
||||||
![This image shows a graph. The x-axis is labeled Noise amplification factor. The y-axis is labeled Expectation value. An upward sloping line is labeled Mitigated value. Points near the line are noise-amplified values. There is a horizontal line just above the X-axis labeled Exact value. ](/images/optimize/resiliance-2.png "Illustration of the ZNE method")
|
|
||||||
|
|
||||||
The overhead of this method scales with the number of noise factors. The
|
|
||||||
default settings sample the expectation value at three noise factors,
|
|
||||||
leading to a roughly 3x overhead when employing this resilience level.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Resilience Level 3</summary>
|
|
||||||
|
|
||||||
Level 3 enables the Probabilistic Error Cancelation (PEC) method. This
|
|
||||||
approach mitigates error by learning and inverting a sparse noise model
|
|
||||||
that is able to capture correlated noise. PEC returns an unbiased
|
|
||||||
estimate of an expectation value so long as learned noise model
|
|
||||||
faithfully represents the actual noise model at the time of mitigation.
|
|
||||||
In practice, the experimental procedure for learning the noise model has
|
|
||||||
ambiguities due to certain error terms that cannot be independently
|
|
||||||
distinguished. These are resolved by a symmetry assumption, which
|
|
||||||
depending on the true underlying noise may lead a biased estimate of the
|
|
||||||
mitigated expectation values due to using an imperfect noise model.
|
|
||||||
|
|
||||||
The Qiskit Runtime primitive implementation of PEC specifically
|
|
||||||
addresses noise in self-inverse two-qubit gates, so it first
|
|
||||||
_stratifies_ each input circuit into an alternating sequence of
|
|
||||||
simultaneous 1-qubit gates followed by a layer of simultaneous 2-qubit
|
|
||||||
gates. Then it learns the noise model associated with each unique
|
|
||||||
2-qubit gate layer.
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<img src="/images/optimize/stratified.png" alt="Stratified circuit illustration. There are arbitrary single-qubit gates between each `layer`. Each layer is defined by a block that crosses multiple qubit wires." />
|
|
||||||
<figcaption>This is an example of a <span
|
|
||||||
class="title-ref">stratified</span> circuit, where the layers of
|
|
||||||
two-qubit gates are labeled layer 1 through n. Note that each <span
|
|
||||||
class="math inline"><em>U</em><sub><em>n</em></sub></span> is composed
|
|
||||||
of two-qubit gates on the native connectivity graph of the quantum
|
|
||||||
processor. The open boxes represent arbitrary single-qubit
|
|
||||||
gates.</figcaption>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
The overhead of this method scales with the number of noise factors. The
|
|
||||||
default settings sample the expectation value at three noise factors,
|
|
||||||
leading to a roughly 3x overhead when employing this resilience level.
|
|
||||||
|
|
||||||
PEC uses a quasi-probability method to mimic the effect of inverting the
|
|
||||||
learned noise. This requires sampling from a randomized circuit family
|
|
||||||
associated with the user's original circuit. Applying PEC will increase
|
|
||||||
the variability of the returned expectation value estimates unless the
|
|
||||||
number of samples per circuit is also increased for both input and
|
|
||||||
characterization circuits. The amount of samples required to counter
|
|
||||||
this variability scales exponentially with the noise strength of the
|
|
||||||
mitigated circuit.
|
|
||||||
|
|
||||||
How this works:
|
|
||||||
|
|
||||||
When estimating an unmitigated Pauli observable $\\langle P\\rangle$ the
|
|
||||||
standard error in the estimated expectation value is given by
|
|
||||||
|
|
||||||
$\\frac{1}{\\sqrt{N\_{\\text{shots}}}}\\left(1- \\langle P\\rangle^2\\right)$
|
|
||||||
|
|
||||||
where $N_{\\text{shots}}$ is the number of shots used to estimate
|
|
||||||
$\\langle P\\rangle$. When applying PEC mitigation, the standard error
|
|
||||||
becomes
|
|
||||||
$\\sqrt{\\frac{S}{N_{\\text{samples}}}}\\left(1- \\langle P\\rangle^2\\right)$
|
|
||||||
where $N\_{\\text{samples}}$ is the number of PEC samples.
|
|
||||||
|
|
||||||
The sampling overhead scales exponentially with a parameter that
|
|
||||||
characterizes the collective noise of the input circuit. As the Qiskit
|
|
||||||
Runtime primitive learns the noise of your circuit, it will return
|
|
||||||
metadata about the sampling overhead associated with that particular
|
|
||||||
layer. Let's label the overhead of layer $l$ as $\\gamma_l$. Then the
|
|
||||||
total sampling overhead for mitigating your circuit is the product of
|
|
||||||
all the layer overheads, that is:
|
|
||||||
|
|
||||||
$S = \\prod_l \\gamma_l$
|
|
||||||
|
|
||||||
When the Estimator completes the model-learning phase of the primitive
|
|
||||||
query, it will return metadata about the total sampling overhead for
|
|
||||||
circuit.
|
|
||||||
|
|
||||||
Depending on the precision required by your application, you will need
|
|
||||||
to scale the number of samples accordingly. The following plot
|
|
||||||
illustrates the relationship between estimator error and number of
|
|
||||||
circuit samples for different total sampling overheads.
|
|
||||||
|
|
||||||
![This image shows that the error decreases as the number of samples increases. The accuracy is best with a high sampling overhead (1000) and worst with a low sampling overhead (1.1).](/images/optimize/sampling-overhead.png)
|
|
||||||
|
|
||||||
Note that the number of samples required to deliver a desired accuracy
|
|
||||||
is not known before the primitive query because the mitigation scaling
|
|
||||||
factor is discovered during the learning phase of PEC.
|
|
||||||
|
|
||||||
We suggest starting with short depth circuits to get a feel for the
|
|
||||||
scaling of the sampling overhead of PEC before attempting larger
|
|
||||||
problems.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
The Estimator interface lets users seamlessly work with the variety of
|
|
||||||
error mitigation methods to reduce error in expectation values of
|
|
||||||
observables. The following code uses Zero Noise Extrapolation by simply
|
|
||||||
setting `resilience_level 2`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
options = Options()
|
|
||||||
options.resilience_level = 2
|
|
||||||
options.optimization_level = 3
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
estimator = Estimator(options=options, backend=backend)
|
|
||||||
job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1])
|
|
||||||
psi1_H1 = job.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="info" title="Note">
|
|
||||||
|
|
||||||
As you increase the resilience level, you will be able to use additional methods to improve the accuracy of your result. However, because the methods become more advanced with each level, they require additional sampling overhead (time) to generate more accurate expectation values. Note that higher resilience levels do not guarantee better quality. Higher levels only mean greater overhead. Each method has its strengths and weaknesses. For example, TREX (Twirled Readout Error eXtinction) is good for shallow circuits because of its readout error mitigation, whereas ZNE (Zero Noise Extrapolation) is good for deeper circuits. PEC can mitigate arbitrary errors but may not work in practice because of its large overhead.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Configure Sampler with resilience levels
|
|
||||||
|
|
||||||
The Sampler default resilience setting (level 1) enables readout error
|
|
||||||
mitigation to allow users to generate mitigated quasi-probability
|
|
||||||
distributions.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Resilience Level 1</summary>
|
|
||||||
|
|
||||||
Level 1 uses matrix-free measurement mitigation (M3) routine to mitigate
|
|
||||||
readout error. M3 works in a reduced subspace defined by the noisy input
|
|
||||||
bit strings that are to be corrected. Because the number of unique bit
|
|
||||||
strings can be much smaller than the dimensionality of the full
|
|
||||||
multi-qubit Hilbert space, the resulting linear system of equations is
|
|
||||||
nominally much easier to solve.
|
|
||||||
|
|
||||||
![Illustration of the M3 method.](/images/optimize/m3.png "M3 method")
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
options = Options()
|
|
||||||
options.resilience_level = 1
|
|
||||||
options.optimization_level = 3
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
sampler = Sampler(backend, options=options)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Advanced resilience options
|
|
||||||
|
|
||||||
You can tune advanced options to configure your resilience strategy
|
|
||||||
further. These methods can be used alongside resilience levels where you
|
|
||||||
change the specific options of interest and let your previously set
|
|
||||||
resilience level manage the rest.
|
|
||||||
|
|
||||||
As a part of the beta release of the resilience options, users will be
|
|
||||||
able configure ZNE by using the following advanced options. We will soon
|
|
||||||
add options to tune other resilience levels that include PEC.
|
|
||||||
|
|
||||||
| Options | Inputs | Description |
|
|
||||||
| ----------------------------------------------------------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `options.resilience.noise_amplifier(Optional\[str\])` <br/> select your amplification strategy | `TwoQubitAmplifier` [Default] | Amplifies noise of all performing local gate folding. |
|
|
||||||
| | `CxAmplifier` | Amplifies noise of all CNOT gates by performing local gate folding. |
|
|
||||||
| | `LocalFoldingAmplifier` | Amplifies noise of all gates by performing local gate folding. |
|
|
||||||
| | `GlobalFoldingAmplifier` | Amplifies noise of the input circuit by performing global folding of the entire input circuit. |
|
|
||||||
| `options.resilience.noise_factors(Optional[Sequence[float]])` | (1, 3, 5)[Default] | Noise amplification factors, where [1] represents the baseline noise. They all need to be greater than or equal to the baseline. |
|
|
||||||
| `options.resilience.extrapolator(Optional\[str\])` | `LinearExtrapolator`\[Default] | Polynomial extrapolation of degree one. |
|
|
||||||
| | `Quadratic Extrapolator` | Polynomial extrapolation of degree two and lower. |
|
|
||||||
| | `Cubic Extrapolator` | Polynomial extrapolation of degree three and lower. |
|
|
||||||
| | `Quartic Extrapolator` | Polynomial extrapolation of degree four and lower. |
|
|
||||||
|
|
||||||
### Example of adding `resilience_options` with the Estimator primitive
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
options = Options()
|
|
||||||
options.optimization_level = 3
|
|
||||||
options.resilience_level = 2
|
|
||||||
options.resilience.noise_factors = (1, 2, 3, 4)
|
|
||||||
options.resilience.noise_amplifier = 'CxAmplifier'
|
|
||||||
options.resilience.extrapolator = 'QuadraticExtrapolator'
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
|
|
||||||
estimator = Estimator(options=options, backend=backend)
|
|
||||||
job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1])
|
|
||||||
psi1_H1 = job.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Walk through an example that uses error mitigation in the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum Learning.
|
|
||||||
- Learn more about [Q-CTRL](https://docs.q-ctrl.com/q-ctrl-embedded).
|
|
||||||
</Admonition>
|
|
|
@ -1,129 +0,0 @@
|
||||||
---
|
|
||||||
title: Configure runtime compilation
|
|
||||||
description: How to use runtime compilation techniques
|
|
||||||
---
|
|
||||||
|
|
||||||
# Configure runtime compilation for Qiskit Runtime
|
|
||||||
|
|
||||||
Runtime compilation techniques optimize and transform your circuit to minimize errors. Runtime compilation adds some classical pre-processing overhead to your overall runtime. Therefore, it is important to achieve a balance between perfecting your results and ensuring that your job completes in a reasonable amount of time.
|
|
||||||
|
|
||||||
Primitives let you employ runtime compilation by setting the optimization level (`optimization_level` option) and by choosing advanced runtime compilation options.
|
|
||||||
|
|
||||||
## Set the optimization level
|
|
||||||
|
|
||||||
The `optimization_level` setting specifies how much optimization to perform on the circuits. Higher levels generate more optimized circuits, at the expense of longer compile times.
|
|
||||||
|
|
||||||
<Admonition>
|
|
||||||
In current primitive versions, optimization levels 2 and 3 behave identically to level 1.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Table>
|
|
||||||
<thead>
|
|
||||||
<Tr>
|
|
||||||
<Th>Optimization Level</Th>
|
|
||||||
<Th>Estimator & Sampler</Th>
|
|
||||||
</Tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<Tr>
|
|
||||||
<Td>0</Td>
|
|
||||||
<Td>
|
|
||||||
No optimization: typically used for hardware characterization or debugging
|
|
||||||
|
|
||||||
```
|
|
||||||
- Basis translation
|
|
||||||
- Layout (as specified)
|
|
||||||
- Routing (stochastic swaps)
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
<Tr>
|
|
||||||
<Td>1, 2, 3</Td>
|
|
||||||
<Td>
|
|
||||||
Light optimization:
|
|
||||||
|
|
||||||
- Layout (trivial → vf2 → SabreLayout if routing is required)
|
|
||||||
- Routing (SabreSWAPs if needed)
|
|
||||||
- 1Q gate optimization
|
|
||||||
- Error suppression: dynamical decoupling
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
```
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<Admonition>
|
|
||||||
The primitives expect circuits in a form suitable to execute on the target system. You may use the Qiskit transpiler locally to translate abstract circuits into this target circuit form.
|
|
||||||
|
|
||||||
At present, the primitives will attempt low-cost transformations if given a circuit that is not already in target form, but in the future, primitives will error on such circuits. It is therefore recommended that users take advantage of the local compilation capabilities of the Qiskit transpiler wherever possible.
|
|
||||||
|
|
||||||
For instructions on preparing circuits for primitive queries, see the [Submit pre-transpiled circuits](https://learning.quantum.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives) tutorial.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If using an IBM Cloud Qiskit Runtime service instance with Q-CTRL performance management enabled, there is no need to specify runtime optimization or resilience levels, as the strategy includes an automatic preset.
|
|
||||||
|
|
||||||
Q-CTRL defaults to `optimization_level=3` and `resilience_level=1`.
|
|
||||||
Setting `optimization_level` or `resilience_level` equal to 0 will result in an
|
|
||||||
execution error. Levels 1, 2, and 3 are permitted but will not impact performance.
|
|
||||||
Setting other options will likewise not impact performance, and it may result in a
|
|
||||||
runtime warning. For more information visit the [Q-CTRL documentation](https://docs.q-ctrl.com/q-ctrl-embedded).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Example: configure Estimator with optimization levels
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options
|
|
||||||
from qiskit.circuit.library import RealAmplitudes
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
options = Options(optimization_level=1)
|
|
||||||
|
|
||||||
psi = RealAmplitudes(num_qubits=2, reps=2)
|
|
||||||
H = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
|
|
||||||
theta = [0, 1, 1, 2, 3, 5]
|
|
||||||
|
|
||||||
estimator = Estimator (options=options, backend=backend)
|
|
||||||
|
|
||||||
job = estimator.run(circuits=[psi], observables=[H], parameter_values=[theta])
|
|
||||||
psi1_H1 = job.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If the optimization level is not specified, the service uses `optimization_level = 1`.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Example: configure Sampler with optimization levels
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
options = Options(optimization_level=1)
|
|
||||||
|
|
||||||
sampler = Sampler(options=options, backend=backend)
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="transpilation-table"></span>
|
|
||||||
## Advanced runtime compilation options
|
|
||||||
|
|
||||||
You also have the ability to tune a variety of advanced options to configure your runtime compilation strategy further. These methods can be used alongside optimization levels. They allow you to change the options of interest and let your optimization level manage the rest.
|
|
||||||
|
|
||||||
| Options | Description |
|
|
||||||
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| options.transpilation.skip_transpilation (bool) | Directs the service to execute the primitive query with the bare minimum about of runtime compilation necessary |
|
|
||||||
| options.transpilation.initial_layout(Union\[dict, List, None]) | (Deprecated) Initial position of virtual qubits on physical qubits. |
|
|
||||||
| options.transpilation.layout_method (Optional\[str]) | (Deprecated) Name of layout selection pass. One of `trivial`, `dense`, `noise_adaptive`, `sabre`. |
|
|
||||||
| options.transpilation.routing_method (Optional\[str]) | (Deprecated) Name of routing pass: `basic`, `lookahead`, `stochastic`, `sabre`, `none`. |
|
|
||||||
| options.transpilation.approximation_degree (Optional\[float]) | (Deprecated) Heuristic dial used for circuit approximation (1.0=no approximation, 0.0=maximal approximation). Defaults to no approximation for all optimization levels |
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try a tutorial that uses optimization levels, such as the [Variational quantum eigensolver](https://learning.quantum.ibm.com/tutorial/variational-quantum-eigensolver) tutorial.
|
|
||||||
- Learn how to transpile locally in the [Transpile](../transpile/) section.
|
|
||||||
- Try the [Submit pre-transpiled circuits](https://learning.quantum.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives) tutorial.
|
|
||||||
</Admonition>
|
|
|
@ -1,65 +0,0 @@
|
||||||
{
|
|
||||||
"cells": [
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"# Hardware considerations and limitations for classical feedforward and control flow\n",
|
|
||||||
"\n",
|
|
||||||
"[Classical feedforward and control flow](/build/classical-feedforward-and-control-flow) shows how to use Qiskit to build circuits that involve classical feedforward and control flow, also known as dynamic circuits. When actually running such circuits on quantum hardware, there are several considerations and limitations to be aware of. Many of these limitations exist because the underlying technology supporting these features is in an early stage of development, and we hope to be able to address them in the future.\n",
|
|
||||||
"\n",
|
|
||||||
"## Primitives do not currently support classical feedforward and control flow\n",
|
|
||||||
"\n",
|
|
||||||
"Currently, circuits with classical control flow cannot be executed with the Qiskit Runtime primitives. The only way to run them on hardware is to use the `backend.run` function, where `backend` is an IBMBackend object. Furthermore, when using `backend.run` to execute such circuits, you must pass the `dynamic=True` argument. For example:\n",
|
|
||||||
"\n",
|
|
||||||
"```python\n",
|
|
||||||
"job = backend.run(circuit, dynamic=True)\n",
|
|
||||||
"```\n",
|
|
||||||
"\n",
|
|
||||||
"## Memory limits and latency in control hardware\n",
|
|
||||||
"\n",
|
|
||||||
"![Diagram showing control hardware architecture](/images/run/rta-architecture.png)\n",
|
|
||||||
"\n",
|
|
||||||
"Running circuits on quantum processors involves not only the qubits themselves, but also a system of classical electronics and computers to generate and receive waveforms and orchestrate the control logic. When a job is submitted to the IBM Quantum service, it is processed into multiple classical programs that must be distributed between two kinds of units: central controllers and qubit controllers (see diagram above). A job may fail if it exceeds certain limitations of these controllers. There are two kinds of limitations to be aware of:\n",
|
|
||||||
"\n",
|
|
||||||
"- **Limited working memory**. This primarily affects the central controllers, and jobs will fail if they cause this memory limit to be exceeded.\n",
|
|
||||||
"- **Latency caused by classical computation**. Running circuits that use classical feedforward and control flow involves performing classical computation during the course of the circuit execution. Due to the limited coherence time of qubits, there is a limited time budget for performing these computations. A job may fail at compile time if the compilation detects that the classical computation overhead is too large.\n",
|
|
||||||
"\n",
|
|
||||||
"The memory requirements and classical latencies of a job are affected by the following factors:\n",
|
|
||||||
"\n",
|
|
||||||
"- **Number of circuits**. When multiple circuits are submitted in a single job, they become concatenated into a single large circuit, with qubit initialization operations between them. Qubit initialization is implemented as a conditional reset on all qubits used in the large circuit.\n",
|
|
||||||
" - Central controller: Memory usage scales proportionally with the number of circuits.\n",
|
|
||||||
"- **Amount of control flow**.\n",
|
|
||||||
" - Central controller: Memory usage scales proportionally with the number of control flow decisions.\n",
|
|
||||||
" - Qubit controller: A control flow construct with too many or too large logic branches may not be realizable.\n",
|
|
||||||
"- **Resets**.\n",
|
|
||||||
" - Central controller: Memory usage scales proportionally with the number of resets.\n",
|
|
||||||
"- **Measurements**.\n",
|
|
||||||
" - Central controller: Memory usage scales proportionally with the number of measurements used by the central controller for control flow."
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Article on hardware considerations and limitations for classical feedforward and control flow",
|
|
||||||
"kernelspec": {
|
|
||||||
"display_name": "Python 3",
|
|
||||||
"language": "python",
|
|
||||||
"name": "python3"
|
|
||||||
},
|
|
||||||
"language_info": {
|
|
||||||
"codemirror_mode": {
|
|
||||||
"name": "ipython",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"file_extension": ".py",
|
|
||||||
"mimetype": "text/x-python",
|
|
||||||
"name": "python",
|
|
||||||
"nbconvert_exporter": "python",
|
|
||||||
"pygments_lexer": "ipython3",
|
|
||||||
"version": "3.10.13"
|
|
||||||
},
|
|
||||||
"title": "Hardware considerations and limitations for classical feedforward and control flow"
|
|
||||||
},
|
|
||||||
"nbformat": 4,
|
|
||||||
"nbformat_minor": 2
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
---
|
|
||||||
title: Estimate job run time
|
|
||||||
description: Estimate how long a job that uses a primitive will take to run
|
|
||||||
---
|
|
||||||
|
|
||||||
# Estimate job run time
|
|
||||||
|
|
||||||
After submitting a job to the IBM Quantum channel, you can see an estimation for how much _quantum time_ the job will take to run by using `job.usage_estimation`. Alternatively, you can [view this information on the IBM Quantum Platform user interface](#view-usage).
|
|
||||||
|
|
||||||
Quantum time is the duration, in seconds, a quantum system is committed to fulfilling a user request.
|
|
||||||
|
|
||||||
<Admonition type="note" title="Notes">
|
|
||||||
- This only applies to jobs that use primitives.
|
|
||||||
- This is not yet available on the IBM Qiskit Runtime on Cloud channel.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
# Create a new circuit with two qubits (first argument) and two classical
|
|
||||||
# bits (second argument)
|
|
||||||
qc = QuantumCircuit(2, 2)
|
|
||||||
|
|
||||||
# Add a Hadamard gate to qubit 0
|
|
||||||
qc.h(0)
|
|
||||||
|
|
||||||
# Perform a controlled-X gate on qubit 1, controlled by qubit 0
|
|
||||||
qc.cx(0, 1)
|
|
||||||
|
|
||||||
# Measure qubit 0 to cbit 0, and qubit 1 to cbit 1
|
|
||||||
qc.measure(0, 0)
|
|
||||||
qc.measure(1, 1)
|
|
||||||
|
|
||||||
# Run on the least-busy system you have access to
|
|
||||||
backend = service.least_busy(simulator=False,operational=True)
|
|
||||||
|
|
||||||
# Create a Sampler object
|
|
||||||
sampler = Sampler(backend)
|
|
||||||
|
|
||||||
# Submit the circuit to the sampler
|
|
||||||
job = sampler.run(qc)
|
|
||||||
|
|
||||||
print(job.usage_estimation)
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
|
|
||||||
```python
|
|
||||||
{'quantum_seconds': 4.1058720028432445}
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="view-usage"></span>
|
|
||||||
## View the estimated job usage on IBM Quantum Platform
|
|
||||||
|
|
||||||
You can view the estimated usage (how much quantum time the job will take to run) in two places on IBM Quantum Platform:
|
|
||||||
|
|
||||||
- On the [Jobs table](https://quantum.ibm.com/jobs) in the Usage column. From the Home page, click _View all_ on the Recent jobs table. The Usage column shows the estimated usage for pending jobs, or actual usage for completed jobs.
|
|
||||||
- On the job's details page. From the [Dashboard](https://quantum.ibm.com/) or [Jobs table](https://quantum.ibm.com/jobs), click the job ID to open the job details page. The estimated usage is shown in the Status Timeline.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Review these tips: [Minimize job run time](minimize-time).
|
|
||||||
- Set the [Maximum execution time](max-execution-time).
|
|
||||||
</Admonition>
|
|
|
@ -1,69 +0,0 @@
|
||||||
---
|
|
||||||
title: Fair-share queue
|
|
||||||
description: How the IBM Quantum fair-share queue determines order of jobs submitted to quantum systems
|
|
||||||
---
|
|
||||||
|
|
||||||
# Fair-share queue
|
|
||||||
|
|
||||||
When you submit a job to a quantum system, it enters the scheduler for the specific system, joining the pool of jobs (from all users) that are waiting to be executed on that system. The order in which these jobs are executed is, by default, determined by a fair-share formula. As discussed below, this algorithm attempts to balance the workload between different [instances](instances) according to the allocated system access amount over a given time window. In practice, this means that jobs from various instances are interweaved in a non-trivial manner, and the order in which jobs complete is not necessarily the order in which they were submitted. Because the queue order is calculated dynamically as new jobs arrive, it is generally impossible to guarantee when a fair-share job will be executed.
|
|
||||||
|
|
||||||
## Fair-share terms
|
|
||||||
|
|
||||||
- **Provider:** An entity providing access to quantum computing. IBM Quantum Platform and IBM Cloud® are providers of Qiskit Runtime services.
|
|
||||||
- **Instance:** A combination of hub/group/project.
|
|
||||||
- **Hub:** Represents the top level of an organization such as an academic, industry, or research partner.
|
|
||||||
- **Group:** A mid-level structure to which access shares can be allocated by the hub for one or more collections of users (projects).
|
|
||||||
- **Project:** The base-level construct to which shares are allocated from the overarching group, and to which users are directly assigned.
|
|
||||||
- **Access share:** (This documentation uses the simplified term “share”.) A relative amount of access to IBM Quantum computing services assigned to a specific hub, group and project. The portion of access is determined by the specific allotment of shares divided by the total number of shares distributed. IBM Quantum assigns to each hub a share of the overall computational capacity of the IBM Quantum Premium Plan. Hub administrators then assign fractions of their share pool to each of their groups. Finally, group administrators assign fractions (also called shares) of their share pool to each of their projects.
|
|
||||||
- **Scheduling window:** The fair-share algorithm accounts for usage over a rolling time window. Only execution time accumulated within that window is accounted for the purpose of fairness. The length of that window is currently 28 days. When the fair-share algorithm is invoked, it takes into account usage starting 28 days ago.
|
|
||||||
- **Time used:** For every group and project, during the scheduling window, we account for all usage on all the systems of the IBM Quantum Premium Plan. These include all successful jobs, as well as jobs returning known select errors. It does not account for canceled jobs, even when partially executed.
|
|
||||||
- **Fair-share algorithm:** For each group and project, the duration of the scheduling window is used to convert shares into an equivalent amount of time that an instance would receive under ideal conditions. The ratio between the time used and the shares equivalent time is used as the basis for scheduling jobs.
|
|
||||||
|
|
||||||
## Shares and administration
|
|
||||||
|
|
||||||
A hub’s entitlement determines its proportional share of the IBM Quantum Premium Plan computational capacity. IBM Quantum assigns shares to hubs. Hub administrators then decide what portion of these shares to assign to each of their groups. Similarly, group administrators will decide what portion of shares to assign to each of their projects.
|
|
||||||
|
|
||||||
![Screenshot of the Administrator user interface.](/images/migration/admin-UI1.png "Administrator user interface")
|
|
||||||
|
|
||||||
Hub administration user interface. This is used to assign shares to groups. The entire hub share pool is distributed to the underlying groups, and the hub administrator can control the percent distribution by specifying a share value for each group. In this example, Group 5 receives 2 shares of their hub share pool, over a total of 5 shares across all groups. That means that Group 5 receives 40% of the shares pool that the hub was granted.
|
|
||||||
|
|
||||||
The fair-share algorithm takes into consideration how these shares are distributed across groups and projects to determine job prioritization.
|
|
||||||
|
|
||||||
The scheduling algorithm combines a group’s shares with the shares of its hub, to determine the total fraction of computational power allocated to that group. For example, assume you have set up the following allocations:
|
|
||||||
|
|
||||||
![Two hubs are shown: A, and B. Hub A has allocated 20% to Group A and 40% to group B. Hub B has allocated 30% to group C and 10% to group D.](/images/migration/allocation.png "Allocation example")
|
|
||||||
|
|
||||||
To compute the 60% for Hub-A, start with the 3 shares of Hub-A and divide between all the shares at the hub level (3 + 2 = 5 shares in total). This results in 3/5 = 0.6 = 60%. When computing the fraction per group, repeat the calculation inside each hub; the fractions for Group-A and Group-B would therefore be 33% and 67%, then apply these percentages to the Hub-A fraction, which results in 20% and 40%.
|
|
||||||
|
|
||||||
## How the fair-share queue works
|
|
||||||
|
|
||||||
The fair-share scheduling algorithm select jobs to execute on a quantum system in a dynamic order so that no instance can monopolize the system. When a quantum system is ready for additional work, it requests the next job from the fair-share scheduler. The scheduler selects the next job by first identifying the group that has used the least amount of their share within the scheduling window. If the group has more than one project, and both have jobs waiting to be executed, then the scheduler identifies the project that has used the least of their share within the scheduling window. Finally, if the project has submitted more than one job, the scheduler will select the oldest job first. Thus, within a project, the scheduler works on a first-in-first-out (FIFO) basis.
|
|
||||||
|
|
||||||
In the following example, we have seven instances arranged between two different hubs. As jobs flow through the system, each group and project consumes some fraction of its effective allotted share. The first image below describes the state at time t1. In between brackets we report the consumption as a fraction of the allotted shares. The fair-share algorithm first identifies the group with the smallest number in between brackets, then the project with the least number in the brackets, and finally it selects the oldest job submitted by that project.
|
|
||||||
|
|
||||||
![This image shows how a job might flow through the queue. It shows Group A from Hub A being selected because it has (0.0), then Project B, which is part of Group A is selected because it also has (0.0), then the first job for that project is run. ](/images/migration/fairshare3.png "Fair-share queue example")
|
|
||||||
|
|
||||||
A snapshot view of consumption (in brackets) relative to the assigned shares. This scenario has seven different H/G/Ps arranged into hubs, groups, and projects. The next selected group and or project is the one with the smallest consumed fraction of the assigned shares. In this example, the Hub-A/Group-1/Project-Y is selected, and the oldest job (first submitted) in the project is executed.
|
|
||||||
|
|
||||||
When the system is ready for an additional job, it repeats the selection. In the following image we represent the state of the queue at time t2. Notice that Group A and Project B consumption were updated to account for the previous consumption accrued between t1 and t2.
|
|
||||||
|
|
||||||
![This image shows how a job might flow through the queue. It shows Group D from Hub D being selected because it has (0.1), which is now the smallest value for the groups, then Project F, which is part of Group D is selected because it has (0.0), then the first job for that project is run.](/images/migration/fairshare4.png "Fair-share queue example 2")
|
|
||||||
|
|
||||||
Recomputed fair-share priorities reflecting the previous job execution. A new H/G/P (Hub-B/Group-2/Project-N) is selected based on these updated values.
|
|
||||||
|
|
||||||
Note that when a user sends jobs to a specific IBM Quantum system, the fair-share algorithm accounts takes into account usage across all systems available to the user in the IBM Quantum Premium Plan when determining fairness.
|
|
||||||
|
|
||||||
## What is my job’s position in the queue?
|
|
||||||
|
|
||||||
As described above, all jobs submitted to the scheduler through the same project will execute in FIFO order. However, global execution order is governed by the fair-share algorithm. Consequently, the time between job submission and job execution can fluctuate depending on usage pattern of the instances which have jobs actively waiting for the system.
|
|
||||||
|
|
||||||
A wait-time estimate is provided through IBM Quantum Platform and via Qiskit. The computed time is the result of a scheduling simulation that predicts one possible execution pattern, given the current fair-share ordering of all the jobs waiting for that system and the approximate runtime of each job. The dynamic nature of the fair-share algorithm means that this estimated time is not fixed and can vary, sometimes dramatically. This wait time is also subject to limitations inherent in estimating the execution time for Qiskit Runtime jobs. For these jobs, where an accurate estimation of time is not feasible, the maximum allowed runtime is used as a proxy. In practice, this means that the duration for a Qiskit Runtime job can be over-estimated by up to eight hours, the maximum allowed Qiskit Runtime job duration for Premium Plan users.
|
|
||||||
|
|
||||||
The job’s position in the queue is listed in the **Queue position** column on the [Jobs page](https://quantum.ibm.com/jobs).
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try the [Grover's algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.
|
|
||||||
- Learn how to [Monitor a job](monitor-job).
|
|
||||||
</Admonition>
|
|
|
@ -1,328 +0,0 @@
|
||||||
{
|
|
||||||
"cells": [
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"# Get backend information with Qiskit\n",
|
|
||||||
"\n",
|
|
||||||
"This page explains how to use Qiskit to find information about your available backends."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"## List backends\n",
|
|
||||||
"\n",
|
|
||||||
"To view the backends you have access to, you can either view a list on the [Compute resources page,](https://quantum.ibm.com/services/resources?tab=yours) or you can use the [`QiskitRuntimeService.backends()`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#backends) method. This method returns a list of [`IBMBackend`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.IBMBackend) instances:"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 1,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"[<IBMBackend('ibmq_qasm_simulator')>,\n",
|
|
||||||
" <IBMBackend('ibmq_mumbai')>,\n",
|
|
||||||
" <IBMBackend('ibm_hanoi')>,\n",
|
|
||||||
" <IBMBackend('ibm_osaka')>,\n",
|
|
||||||
" <IBMBackend('ibm_cusco')>,\n",
|
|
||||||
" <IBMBackend('ibm_sherbrooke')>,\n",
|
|
||||||
" <IBMBackend('ibm_nazca')>,\n",
|
|
||||||
" <IBMBackend('ibm_kyoto')>,\n",
|
|
||||||
" <IBMBackend('ibm_cairo')>,\n",
|
|
||||||
" <IBMBackend('ibmq_kolkata')>,\n",
|
|
||||||
" <IBMBackend('ibm_brisbane')>,\n",
|
|
||||||
" <IBMBackend('ibm_algiers')>,\n",
|
|
||||||
" <IBMBackend('ibm_torino')>]"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 1,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"# Initialize your account \n",
|
|
||||||
"from qiskit_ibm_runtime import QiskitRuntimeService\n",
|
|
||||||
"service = QiskitRuntimeService()\n",
|
|
||||||
"\n",
|
|
||||||
"service.backends()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"The [`QiskitRuntimeService.backend()`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#backend) method (note that this is singular: *backend*) takes the name of the backend as the input parameter and returns an [`IBMBackend`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.IBMBackend) instance representing that particular backend:"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 2,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"<IBMBackend('ibmq_qasm_simulator')>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 2,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"service.backend(\"ibmq_qasm_simulator\")"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"## Filter backends\n",
|
|
||||||
"\n",
|
|
||||||
"You can also filter the available backends by their properties. For more general filters, you can make advanced functions using a lambda function. Refer to the [API documentation](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#backends) for more details.\n",
|
|
||||||
"\n",
|
|
||||||
"Let’s try getting only backends that fit these criteria:\n",
|
|
||||||
"\n",
|
|
||||||
"* Are real quantum devices (`simulator=False`)\n",
|
|
||||||
"* Are currently operational (`operational=True`)\n",
|
|
||||||
"* Have at least 5 qubits (`min_num_qubits=5`)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 3,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"[<IBMBackend('ibmq_mumbai')>,\n",
|
|
||||||
" <IBMBackend('ibm_hanoi')>,\n",
|
|
||||||
" <IBMBackend('ibm_osaka')>,\n",
|
|
||||||
" <IBMBackend('ibm_cusco')>,\n",
|
|
||||||
" <IBMBackend('ibm_sherbrooke')>,\n",
|
|
||||||
" <IBMBackend('ibm_nazca')>,\n",
|
|
||||||
" <IBMBackend('ibm_kyoto')>,\n",
|
|
||||||
" <IBMBackend('ibm_cairo')>,\n",
|
|
||||||
" <IBMBackend('ibmq_kolkata')>,\n",
|
|
||||||
" <IBMBackend('ibm_brisbane')>,\n",
|
|
||||||
" <IBMBackend('ibm_algiers')>,\n",
|
|
||||||
" <IBMBackend('ibm_torino')>]"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 3,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"service.backends(simulator=False, operational=True, min_num_qubits=5)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"A similar method is [`QiskitRuntimeService.least_busy()`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#least_busy), which takes the same filters as `backends()` but returns the backend that matches the filters and has the least number of jobs pending in the queue:"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 4,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"<IBMBackend('ibmq_qasm_simulator')>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 4,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"service.least_busy(operational=True, min_num_qubits=5)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"## Static backend information\n",
|
|
||||||
"\n",
|
|
||||||
"Some information about a backend does not change regularly, such as its name, version, the number of qubits it has, and the types of features it supports. This information is available as attributes of the `backend` object.\n",
|
|
||||||
"\n",
|
|
||||||
"The following cell builds a description of a backend."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 5,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"Name: ibm_kyoto\n",
|
|
||||||
"Version: 2\n",
|
|
||||||
"No. of qubits: 127\n",
|
|
||||||
"\n"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"backend = service.backend(\"ibm_kyoto\")\n",
|
|
||||||
"\n",
|
|
||||||
"print(\n",
|
|
||||||
" f\"Name: {backend.name}\\n\"\n",
|
|
||||||
" f\"Version: {backend.version}\\n\"\n",
|
|
||||||
" f\"No. of qubits: {backend.num_qubits}\\n\"\n",
|
|
||||||
")"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"For a full list of attributes, see the [`IBMBackend` API documentation](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.IBMBackend)."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"## Dynamic backend information\n",
|
|
||||||
"\n",
|
|
||||||
"Backends can also have properties that change whenever the backed is calibrated, such as qubit frequency and operation error rates. Backends are usually calibrated every 24 hours, and their properties update after the calibration sequence completes. These properties can be used when optimizing quantum circuits or to construct noise models for a classical simulator.\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"### Qubit properties\n",
|
|
||||||
"\n",
|
|
||||||
"The `backend.qubit_properties` method returns information about the qubits' physical attributes. This includes the qubit frequency in GHz and decay times (`t1` and `t2`) in µs."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 6,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"IBMQubitProperties(t1=0.00016855861574467424, t2=2.3453094185862303e-05, frequency=4908867208.080845, anharmonicity=-308028796.19250304)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 6,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"backend.qubit_properties(0) # properties of qubit 0"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"### Instruction properties\n",
|
|
||||||
"\n",
|
|
||||||
"The `backend.target` attribute is a `qiskit.transpiler.Target` object: an object that contains all the information needed to transpile a circuit for that backend. This includes instruction errors and durations. For example, the following cell gets the properties for an [`ecr` gate](/api/qiskit/qiskit.circuit.library.ECRGate) acting between qubits 1 and 0."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 7,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"InstructionProperties(duration=6.6e-07, error=0.020534632893441818, calibration=Schedule ecr)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 7,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"backend.target[\"ecr\"][(1,0)]"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"The following cell shows the properties for a measurement operation (including the readout error) on qubit 0."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 8,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"InstructionProperties(duration=1.4e-06, error=0.11159999999999992, calibration=Schedule measure)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 8,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"backend.target[\"measure\"][(0,)]"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"## Next steps\n",
|
|
||||||
"\n",
|
|
||||||
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
|
|
||||||
" - Try the [Grover's algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.\n",
|
|
||||||
" - Review the [IBMProvider backend API](/api/qiskit-ibm-provider/qiskit_ibm_provider.IBMProvider#backend) reference.\n",
|
|
||||||
" - Review the [QiskitRuntime backend API](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#backend) reference.\n",
|
|
||||||
"</Admonition>"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Find and filter available backends, get configuration and calibration data programmatically.",
|
|
||||||
"kernelspec": {
|
|
||||||
"display_name": "Python 3",
|
|
||||||
"language": "python",
|
|
||||||
"name": "python3"
|
|
||||||
},
|
|
||||||
"language_info": {
|
|
||||||
"codemirror_mode": {
|
|
||||||
"name": "ipython",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"file_extension": ".py",
|
|
||||||
"mimetype": "text/x-python",
|
|
||||||
"name": "python",
|
|
||||||
"nbconvert_exporter": "python",
|
|
||||||
"pygments_lexer": "ipython3",
|
|
||||||
"version": "3"
|
|
||||||
},
|
|
||||||
"title": "Get backend information with Qiskit"
|
|
||||||
},
|
|
||||||
"nbformat": 4,
|
|
||||||
"nbformat_minor": 4
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduction
|
|
||||||
description: Overview of the Run section, where you'll find information on IBM Quantum systems and executing jobs on them
|
|
||||||
---
|
|
||||||
|
|
||||||
# Introduction
|
|
||||||
|
|
||||||
IBM Quantum maintains the world’s most advanced fleet of quantum systems, with seven [utility-scale](https://www.ibm.com/blog/announcement/new-ibm-quantum-systems-on-the-ibm-cloud/) quantum systems, and more on the way. These systems demonstrate unparalleled reliability, with >95% uptime across the fleet of quantum systems - and unmatched stability, with two-qubit gate error fluctuations no larger than 0.001 over timescales measured in months[^1].
|
|
||||||
|
|
||||||
## The run phase
|
|
||||||
|
|
||||||
In the run phase, you send your quantum program to be executed on a quantum system. This section provides information about IBM Quantum hardware and how to connect to the instances that provide access to quantum systems. You can find details about estimating job run time and cost, running within a session, reserving time on a system, and more.
|
|
||||||
|
|
||||||
The steps during the run phase are:
|
|
||||||
|
|
||||||
1. Using your account credentials, authenticate to the channel of your choice ([IBM Quantum Platform](../start/setup-channel#ibm-quantum-platform) or [IBM Cloud](../start/setup-channel#ibm-cloud)).
|
|
||||||
2. Choose a system or simulator.
|
|
||||||
3. Send a job to a system or simulator.
|
|
||||||
4. View job results.
|
|
||||||
|
|
||||||
[^1]: Median 2Q gate errors measured over all accessible Eagle processors from July 20 to September 20, 2023.
|
|
|
@ -1,109 +0,0 @@
|
||||||
---
|
|
||||||
title: Instances
|
|
||||||
description: What IBM Quantum Platform instances are and how to use them
|
|
||||||
---
|
|
||||||
|
|
||||||
# Instances
|
|
||||||
|
|
||||||
Access to IBM Quantum Platform services is controlled by the **instances** (previously called providers) to which you are assigned. An instance is defined by a hierarchical organization of **hub**, **group**, and **project**. A hub is the top level of a given hierarchy (organization) and contains within it one or more groups. These groups are in turn populated with projects. The combination of hub/group/project is called an instance. Users can belong to more than one instance at any given time.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
IBM Cloud instances are different from IBM Quantum Platform instances. IBM Cloud does not use the hub/group/project structure for user management. This section describes instances in IBM Quantum Platform. To view and create IBM Cloud instances, visit the [IBM Cloud Quantum Instances page](https://cloud.ibm.com/quantum/instances). Click the name of an instance to see details such as your CRN for that instance, what compute resources (programs, systems, and simulators) are available to you by using that instance, and what jobs you have run on that instance.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
![Alice, Bob, and Charlie are all in Hub A. Hub A has Group 1 and 2. Alice and Bob are in Group 1. Charlie is in Group 2. Group 1 has Project X and Y. Alice is in both projects. Bob is only in project X. Group 2 has Project Z. Charlie is in project Z. Therefore, Charlie's instance is Hub-A/Group-2/Project-Z.](/images/run/providers1.jpg "Hub / group / project hierarchy")
|
|
||||||
|
|
||||||
The hub/group/project hierarchy that makes up an IBM Quantum instance.
|
|
||||||
|
|
||||||
Users with a public account automatically belong to the ibm-q/open/main [open plan](#open-plan). For organizations outside of IBM, designated hub or group administrators assign users to instances.
|
|
||||||
|
|
||||||
To see the instances to which you have access, look at the bottom of your [Account page](https://quantum.ibm.com/account).
|
|
||||||
|
|
||||||
![Screenshot of the Account page.](/images/run/find-providers1.png "Instances on the Account page")
|
|
||||||
|
|
||||||
## Find your instances
|
|
||||||
|
|
||||||
You can view a list of your instances on your [account settings page](https://quantum.ibm.com/account), or you can use [the `instances()` method](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#instances).
|
|
||||||
|
|
||||||
## Switch instances
|
|
||||||
|
|
||||||
If you have access to run on multiple instances, the [IBM Quantum interface](https://quantum.ibm.com/) menu bar contains a dropdown that lets you switch between instances. The IBM Quantum Platform dashboard, Compute resources, and Jobs pages display information such as usage metrics, jobs, and systems based on the selected instance.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The instance switcher does not appear in the Administration application.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
If you switch to a different instance, it is remembered the next time you log on and, assuming that it's still a valid instance, information pertaining to that instance is displayed. By default, the first premium instance you have access to is used. If you do not have any premium instances, the first open instance is shown.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The first instance is determined alphabetically.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Instances and jobs
|
|
||||||
|
|
||||||
When you execute a task using an IBM Quantum service (for example, sending circuits to a quantum system or simulator), a **job** instance is returned to you. Regardless of which service is being used, a job can track the progress of the submission through IBM Quantum, and retrieve the final result(s) of the computation. Because services are coupled to instances, the jobs created from these services are also tied to the specific instance being used. Therefore, **if a user is removed from an instance, their jobs and the associated results are no longer accessible**.
|
|
||||||
|
|
||||||
## Open plan
|
|
||||||
|
|
||||||
By default, users who sign up for an IBM Quantum account are assigned to the Open plan and the Open plan's instance, `ibm-q/open/main`. To guarantee that everyone can use the IBM Quantum systems allocated to the plan fairly, **an individual can have no more than three jobs running and/or in the queue (across all systems) at the same time.** Submitting more than three jobs at a time will return error [#3458](../errors#3458), and additional jobs will be canceled.
|
|
||||||
|
|
||||||
Those using the Open plan instance have up to 10 minutes total of system execution time per month, which resets at 00:00:00 UTC on the first of each calendar month. Open plan users can track their system execution time on the [Platform dashboard,](https://quantum.ibm.com/) [Jobs,](https://quantum.ibm.com/jobs) and [Account](https://quantum.ibm.com/account) pages.
|
|
||||||
|
|
||||||
<span id="connect-instance"></span>
|
|
||||||
## Connect to an instance
|
|
||||||
|
|
||||||
You can specify an instance when initializing the service or provider, or when choosing a system. You can copy the service-level code by clicking the three dots by the instance name on the Instances section of the [Account overview page](https://quantum.ibm.com/account).
|
|
||||||
|
|
||||||
### qiskit-ibm-runtime
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
# Optional: List all the instances you can access.
|
|
||||||
service = QiskitRuntimeService(channel='ibm_quantum')
|
|
||||||
print(service.instances())
|
|
||||||
|
|
||||||
# Optional: Specify it at service level. This becomes the default unless overwritten.
|
|
||||||
service = QiskitRuntimeService(channel='ibm_quantum', instance="hub1/group1/project1")
|
|
||||||
backend1 = service.backend("ibmq_manila")
|
|
||||||
|
|
||||||
# Optional: Specify it at the backend level, which overwrites the service-level specification when this backend is used.
|
|
||||||
backend2 = service.backend("ibmq_manila", instance="hub2/group2/project2")
|
|
||||||
|
|
||||||
sampler1 = Sampler(backend=backend1) # this will use hub1/group1/project1
|
|
||||||
sampler2 = Sampler(backend=backend2) # this will use hub2/group2/project2
|
|
||||||
```
|
|
||||||
|
|
||||||
### qiskit-ibm-provider
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_provider import IBMProvider
|
|
||||||
|
|
||||||
provider = IBMProvider(instance="hub1/group1/project1")
|
|
||||||
backend1 = provider.get_backend("ibmq_manila")
|
|
||||||
backend2 = provider.get_backend("ibmq_manila", instance="hub2/group2/project2")
|
|
||||||
|
|
||||||
job1 = backend1.run(...) # this will use hub1/group1/project1
|
|
||||||
job2 = backend2.run(...) # this will use hub2/group2/project2
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
If you do not specify an instance, the code will select one in the following order:
|
|
||||||
|
|
||||||
1. If your account only has access to one instance, it is selected by default.
|
|
||||||
2. If your account has access to multiple instances but only one can access the requested system, the instance with access is selected.
|
|
||||||
3. In all other cases, the code selects the first instance other than `ibm-q/open/main` that has access to the system.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Leaving an instance
|
|
||||||
|
|
||||||
To leave an instance, visit the instance list on your [Account page.](https://quantum.ibm.com/account) Select the instance you wish to leave, then select the overflow menu and choose _Leave instance_.
|
|
||||||
|
|
||||||
![Screenshot of the Account page.](/images/run/leaving1.png "Leave instance")
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try the [Grover's algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.
|
|
||||||
- Review the [IBMProvider instances method](/api/qiskit-ibm-provider/qiskit_ibm_provider.IBMProvider#instances) reference.
|
|
||||||
- Review the [QiskitRuntimeService instances method](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#instances) reference.
|
|
||||||
</Admonition>
|
|
|
@ -1,79 +0,0 @@
|
||||||
---
|
|
||||||
title: Manage cost
|
|
||||||
description: How to manage costs of running jobs on systems when using the Standard plan for IBM Quantum on IBM Cloud.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Manage cost
|
|
||||||
|
|
||||||
The IBM Cloud Quantum Standard plan is not free, except when running jobs on simulators. Use the information in this topic to help you understand how much you’re paying and how to limit your costs.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The information in this topic only applies to those who are using the Standard plan for IBM Quantum on IBM Cloud. There are no costs associated with IBM Quantum Platform Open plan.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Set a cost limit
|
|
||||||
|
|
||||||
An instance administrator can limit how much is spent. To set cost limits, navigate to the [IBM Cloud Instances page](https://cloud.ibm.com/quantum/instances), then click the instance and set the **Cost limit**. The cost limit refers to the total cost of all jobs run with this instance since it was created, and it will always be greater than or equal to the Total cost. After the instance reaches the specified number of total seconds, no further jobs can be run and no more cost is incurred.
|
|
||||||
|
|
||||||
```
|
|
||||||
<Admonition type="note">
|
|
||||||
The cost limit is always specified in US dollars (USD), then converted to runtime seconds. However, for monthly billing purposes, you are charged in your local currency, specified on your IBM Cloud account. Because currency exchange rates can fluctuate, the cost for X runtime seconds might be different when initially calculated in USD than when you’re actually charged in your local currency. As a result, if your local currency is not USD, the total amount charged for the number of seconds specified in this field could vary from the dollar amount you specify.
|
|
||||||
</Admonition>
|
|
||||||
```
|
|
||||||
|
|
||||||
## How to remove a cost limit
|
|
||||||
|
|
||||||
An instance administrator can remove the cost limit. To do so, navigate to the [IBM Cloud Instances page](https://cloud.ibm.com/quantum/instances), then open the instance and click the edit button by the **Cost limit**. Delete the value and click **Save**.
|
|
||||||
|
|
||||||
### What happens when the cost limit is reached
|
|
||||||
|
|
||||||
When the instance’s cost limit is reached, the currently running job is stopped. Its status is set to Canceled with a reason of Ran too long. Any available partial results are kept.
|
|
||||||
|
|
||||||
No further jobs can be submitted by using this instance until the cost limit is increased.
|
|
||||||
|
|
||||||
## How to see what you’re being charged
|
|
||||||
|
|
||||||
You are sent a monthly invoice that provides details about your resource charges. You can check how much has been spent at any time on the [IBM Cloud Billing and usage page](https://cloud.ibm.com/billing).
|
|
||||||
|
|
||||||
Additionally, you can determine cost per instance or per job at any time.
|
|
||||||
|
|
||||||
### View instance cost
|
|
||||||
|
|
||||||
To determine how much has been billed to an instance during the current billing cycle, from the [Instances page](https://cloud.ibm.com/quantum/instances), click the instance to open its details page.
|
|
||||||
|
|
||||||
These are the fields relevant to cost:
|
|
||||||
|
|
||||||
- **Billing cycle usage**: The amount of _quantum time_ used by this instance during the current billing cycle. Quantum time is the duration a quantum system is committed to fulfilling a user request.
|
|
||||||
- **Billing cycle cost**: The total cost of running jobs during the current billing cycle.
|
|
||||||
- **Total usage**: The amount of quantum time used by this instance since it was created.
|
|
||||||
- **Total cost**: The total cost of running jobs on this instance since it was created. Only administrators can set this value.
|
|
||||||
|
|
||||||
You can view your billing cycle on the [Billing and usage page](https://cloud.ibm.com/billing).
|
|
||||||
|
|
||||||
### View job cost
|
|
||||||
|
|
||||||
To determine how much has been billed to each job associated with an instance, from the [Instances page](https://cloud.ibm.com/quantum/instances), click the instance to open its details page. Next, on the left side, click Jobs.
|
|
||||||
|
|
||||||
These are the columns relevant to cost:
|
|
||||||
|
|
||||||
- **Usage**: The amount of quantum time used by this job. Quantum time is the duration a quantum system is committed to fulfilling a user request.
|
|
||||||
- **Cost**: The total cost of running this job.
|
|
||||||
|
|
||||||
## Estimate the cost
|
|
||||||
|
|
||||||
You can estimate how long a job will run, and therefore its cost, by estimating the job run time. For details, see the [Estimate job run time](estimate-job-run-time) topic.
|
|
||||||
|
|
||||||
## Set up spending notifications
|
|
||||||
|
|
||||||
You can set up spending notifications to get notified when your account or a particular service reaches a specific spending threshold that you set. For information, see the [IBM Cloud account Type description](https://cloud.ibm.com/docs/account?topic=account-accounts). IBM Cloud spending notifications must be used with other methods of cost management for several reasons:
|
|
||||||
|
|
||||||
- The notifications trigger only _after_ cost surpasses the specified limit.
|
|
||||||
- Cost is submitted to the billing system hourly. Therefore, a long delay might occur between the job submission and the spending notification being sent.
|
|
||||||
- The billing system can take multiple days to get information to the invoicing system, which might cause further delay in notifications. For more information about how the IBM Cloud billing system works, see [Setting spending notifications](https://cloud.ibm.com/docs/billing-usage?topic=billing-usage-spending).
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Review the [Qiskit Runtime plans](https://cloud.ibm.com/docs/quantum-computing?topic=quantum-computing-plans) available on IBM Cloud.
|
|
||||||
- Review suggestions to [minimize job quantum time.](minimize-time)
|
|
||||||
</Admonition>
|
|
|
@ -1,64 +0,0 @@
|
||||||
---
|
|
||||||
title: Maximum execution time for a Qiskit Runtime job or session
|
|
||||||
description: Describes how long a Qiskit Runtime job or session can run.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Maximum execution time for a Qiskit Runtime job or session
|
|
||||||
|
|
||||||
To ensure fairness and help control costs, there is a maximum amount of time each Qiskit Runtime job and session can run. If a job exceeds this time limit, it is forcibly canceled and a `RuntimeJobMaxTimeoutError` exception is raised. If a session exceeds its limits, any queued jobs are canceled but any jobs that are already running are not.
|
|
||||||
|
|
||||||
<span id="max-job"></span>
|
|
||||||
## Job maximum execution time
|
|
||||||
|
|
||||||
The maximum execution time for a job is the smaller of these values:
|
|
||||||
|
|
||||||
- The value set for max_execution_time
|
|
||||||
- The system-determined job timeout value
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
As of August 7, 2023, the `max_execution_time` value is based on _quantum time_ instead of wall clock time. Quantum time is the duration a quantum system is committed to fulfilling a user request.
|
|
||||||
|
|
||||||
Simulator jobs continue to use wall clock time because they do not have quantum time.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Set the maximum execution time (in seconds) on the job options by using one of the following methods:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Initiate the Options class with parameters
|
|
||||||
options = Options(max_execution_time=360)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Create the options object with attributes and values
|
|
||||||
options = {"max_execution_time": 360}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also find how much quantum time completed jobs have used by returning the job metrics as follows:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Find quantum time used by the job
|
|
||||||
print(f"Quantum time used by job {job.job_id()} was {job.metrics()['usage']['quantum_seconds']} seconds")
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="max-system"></span>
|
|
||||||
### System maximum execution time
|
|
||||||
|
|
||||||
The system calculates an appropriate job timeout value based on the input circuits and options. This system-calculated timeout is capped at 3 hours to ensure fair device usage. If a `max_execution_time` is also specified for the job, the lesser of the two values is used.
|
|
||||||
|
|
||||||
For example, if you specify `max_execution_time=5000` (approximately 83 minutes), but the system determines it should not take more than 5 minutes (300 seconds) to execute the job, then the job is canceled after 5 minutes.
|
|
||||||
|
|
||||||
## Session maximum execution time
|
|
||||||
|
|
||||||
When a session is started, it is assigned a maximum session timeout value. After this timeout is reached, the session is terminated, any jobs that are already running continue running, and any queued jobs that remain in the session are put into a failed state. For instructions to set the session maximum time, see [Specify the session length](run-jobs-in-session#specify-length).
|
|
||||||
|
|
||||||
## Other limitations
|
|
||||||
|
|
||||||
- Inputs to jobs cannot exceed 64MB in size.
|
|
||||||
- Open plan users can use up to 10 minutes of system execution time per month (resets at 00:00 UTC on the first of each month). System execution time is the amount of time that the system is dedicated to processing your job. You can track your monthly usage on the [Platform dashboard,](https://quantum.ibm.com/) [Quantum Platform Jobs page,](https://quantum.ibm.com/jobs) and [Account](https://quantum.ibm.com/account) page.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Estimate job run time](estimate-job-run-time).
|
|
||||||
- Review these tips: [Minimize job run time](minimize-time).
|
|
||||||
</Admonition>
|
|
|
@ -1,21 +0,0 @@
|
||||||
---
|
|
||||||
title: Minimize job run time
|
|
||||||
description: How to minimize the amount of quantum time spent processing and running a job.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Minimize job run time
|
|
||||||
|
|
||||||
There are several ways you can limit the amount of quantum time spent processing and running a job:
|
|
||||||
|
|
||||||
- Run only as many iterations and shots as you need: The time your workload takes (and therefore, its cost) depends on how many jobs you create in a session and how many shots are run in each job. Therefore, you can manage your cost by running only as many jobs and shots as you need.
|
|
||||||
|
|
||||||
- Set limits on execution time: You can limit how long each job or session runs. For details, see [Maximum execution time for a Qiskit Runtime job or session](max-execution-time).
|
|
||||||
|
|
||||||
- Use only the necessary settings for error suppression, error mitigation, and optimization, because higher values can cause your jobs to run longer. See [Algorithm tuning options](advanced-runtime-options), [Configure runtime compilation](configure-runtime-compilation), and [Configure error mitigation](configure-error-mitigation) for details.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Estimate job run time](estimate-job-run-time).
|
|
||||||
- Explore error mitigation in the [Cost functions](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions) course.
|
|
||||||
</Admonition>
|
|
|
@ -1,49 +0,0 @@
|
||||||
---
|
|
||||||
title: Monitor a job
|
|
||||||
description: How to monitor a job submitted to IBM Quantum Platform or IBM Quantum on IBM Cloud
|
|
||||||
---
|
|
||||||
|
|
||||||
# Monitor a job
|
|
||||||
|
|
||||||
Jobs are listed on the Jobs page for your quantum service channel:
|
|
||||||
|
|
||||||
- IBM Cloud channel: From the IBM Cloud console quantum [Instances page](https://cloud.ibm.com/quantum/instances), click the name of your instance, then click the Jobs tab.
|
|
||||||
- IBM Quantum channel: In IBM Quantum Platform, open the [Jobs page](https://quantum.ibm.com/jobs).
|
|
||||||
|
|
||||||
Use the job instance to check the job status or retrieve the results by calling the appropriate command:
|
|
||||||
|
|
||||||
| | |
|
|
||||||
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| job.result() | Review job results immediately after the job completes. Job results are available after the job completes. Therefore, job.result() is a blocking call until the job completes. |
|
|
||||||
| job.job_id() | Return the ID that uniquely identifies that job. Retrieving the job results at a later time requires the job ID. Therefore, it is recommended that you save the IDs of jobs you might want to retrieve later. |
|
|
||||||
| job.status() | Check the job status. |
|
|
||||||
| job = service.job(\<job_id>) | Retrieve a job you previously submitted. This call requires the job ID. |
|
|
||||||
|
|
||||||
<span id="retrieve-later"></span>
|
|
||||||
## Retrieve job results at a later time
|
|
||||||
|
|
||||||
Call `service.job(\<job\how_toID>)` to retrieve a job you previously submitted. If you don’t have the job ID, or if you want to retrieve multiple jobs at once; including jobs from retired systems, call `service.jobs()` with optional filters instead. See [QiskitRuntimeService.jobs](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#jobs).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
service.jobs() returns only Qiskit Runtime jobs. To retrieve other jobs, use [qiskit-ibm-provider](../api/qiskit-ibm-provider/qiskit_ibm_provider.IBMBackend#ibmbackend) instead.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
This example returns the 10 most recent runtime jobs that were run on `my_backend`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
# Initialize the account first.
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
service.jobs(backend_name=my_backend)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try the [Grover's algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.
|
|
||||||
- Review the [Qiskit tools documentation](/api/qiskit/tools) in the Qiskit Terra API reference.
|
|
||||||
</Admonition>
|
|
|
@ -1,103 +0,0 @@
|
||||||
---
|
|
||||||
title: Native gates and operations
|
|
||||||
description: Summary of the native gates and operations supported by IBM Quantum systems
|
|
||||||
---
|
|
||||||
|
|
||||||
# Native gates and operations
|
|
||||||
|
|
||||||
Each [processor family](processor-types) has a native gate set. By default, the systems in each family only support running the gates and operations in the native gate set. Thus, every gate in the circuit must be translated (by the transpiler) to the elements of this set.
|
|
||||||
|
|
||||||
You can view the native gates and operations for a system either [with Qiskit](#native-gates-with-qiskit) or on the IBM Quantum Platform [Compute resources page](#native-gates-on-platform).
|
|
||||||
|
|
||||||
<Admonition type="note" title="Basis gates">
|
|
||||||
The terms native gates and basis gates are often used interchangeably. However, you can specify a different set of basis gates to use, while the native gate set never changes. For information about changing the basis gates, see the [Represent quantum computers](../transpile/representing_quantum_computers#basis-gates) topic.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Find the native gate set for a system
|
|
||||||
|
|
||||||
<span id="native-gates-with-qiskit"></span>
|
|
||||||
### With Qiskit
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum")
|
|
||||||
|
|
||||||
for backend in service.backends():
|
|
||||||
config = backend.configuration()
|
|
||||||
if "simulator" in config.backend_name:
|
|
||||||
continue
|
|
||||||
print(f"Backend: {config.backend_name}")
|
|
||||||
print(f" Processor type: {config.processor_type}")
|
|
||||||
print(f" Supported instructions:")
|
|
||||||
for instruction in config.supported_instructions:
|
|
||||||
print(f" {instruction}")
|
|
||||||
print()
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="native-gates-on-platform"></span>
|
|
||||||
### On IBM Quantum Platform
|
|
||||||
|
|
||||||
Select any system on the [Compute resources](https://quantum.ibm.com/services/resources) tab. The default gates for that system are listed under Details. Note that the non-unitary operations are not listed here; use the method in Qiskit described above to see all native gates and operations for a system.
|
|
||||||
|
|
||||||
## Tables of gates and operations, by processor family
|
|
||||||
|
|
||||||
### Heron
|
|
||||||
|
|
||||||
| Name | Notes |
|
|
||||||
| :----------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| [CZ](/api/qiskit/qiskit.circuit.library.CZGate) | two-qubit gate |
|
|
||||||
| [RZ](/api/qiskit/qiskit.circuit.library.RZGate) | single-qubit gate |
|
|
||||||
| [SX](/api/qiskit/qiskit.circuit.library.SXGate) | single-qubit gate |
|
|
||||||
| [X](/api/qiskit/qiskit.circuit.library.XGate) | single-qubit gate |
|
|
||||||
| [ID](/api/qiskit/qiskit.circuit.library.IGate) | single-qubit gate wait cycle |
|
|
||||||
| [reset](/api/qiskit/qiskit.circuit.library.Reset) | single-qubit gate, non-unitary; not the same as the initialization done at the start of a circuit to prepare the all 0's state |
|
|
||||||
| [if_else](/api/qiskit/qiskit.circuit.IfElseOp) | control flow for classical feedforward |
|
|
||||||
| [for_loop](/api/qiskit/qiskit.circuit.ForLoopOp) | control flow for classical feedforward |
|
|
||||||
| [switch_case](/api/qiskit/qiskit.circuit.SwitchCaseOp) | control flow for classical feedforward |
|
|
||||||
| [measure](/api/qiskit/qiskit.circuit.library.Measure) | |
|
|
||||||
| [delay](/api/qiskit/qiskit.circuit.Delay) | |
|
|
||||||
|
|
||||||
### Eagle
|
|
||||||
|
|
||||||
| Name | Notes |
|
|
||||||
| :----------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| [ECR](/api/qiskit/qiskit.circuit.library.ECRGate) | two-qubit gate |
|
|
||||||
| [RZ](/api/qiskit/qiskit.circuit.library.RZGate) | single-qubit gate |
|
|
||||||
| [SX](/api/qiskit/qiskit.circuit.library.SXGate) | single-qubit gate |
|
|
||||||
| [X](/api/qiskit/qiskit.circuit.library.XGate) | single-qubit gate |
|
|
||||||
| [ID](/api/qiskit/qiskit.circuit.library.IGate) | single-qubit gate wait cycle |
|
|
||||||
| [reset](/api/qiskit/qiskit.circuit.library.Reset) | single-qubit gate, non-unitary; not the same as the initialization done at the start of a circuit to prepare the all 0's state |
|
|
||||||
| [if_else](/api/qiskit/qiskit.circuit.IfElseOp) | control flow for classical feedforward |
|
|
||||||
| [for_loop](/api/qiskit/qiskit.circuit.ForLoopOp) | control flow for classical feedforward |
|
|
||||||
| [switch_case](/api/qiskit/qiskit.circuit.SwitchCaseOp) | control flow for classical feedforward |
|
|
||||||
| [measure](/api/qiskit/qiskit.circuit.library.Measure) | |
|
|
||||||
| [delay](/api/qiskit/qiskit.circuit.Delay) | |
|
|
||||||
|
|
||||||
### Falcon
|
|
||||||
|
|
||||||
| Name | Notes |
|
|
||||||
| :----------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| [CX](/api/qiskit/qiskit.circuit.library.CXGate) | two-qubit gate |
|
|
||||||
| [RZ](/api/qiskit/qiskit.circuit.library.RZGate) | single-qubit gate |
|
|
||||||
| [ID](/api/qiskit/qiskit.circuit.library.IGate) | single-qubit gate wait cycle |
|
|
||||||
| [reset](/api/qiskit/qiskit.circuit.library.Reset) | single-qubit gate, non-unitary; not the same as the initialization done at the start of a circuit to prepare the all 0's state |
|
|
||||||
| [if_else](/api/qiskit/qiskit.circuit.IfElseOp) | control flow for classical feedforward |
|
|
||||||
| [for_loop](/api/qiskit/qiskit.circuit.ForLoopOp) | control flow for classical feedforward |
|
|
||||||
| [switch_case](/api/qiskit/qiskit.circuit.SwitchCaseOp) | control flow for classical feedforward |
|
|
||||||
| [measure](/api/qiskit/qiskit.circuit.library.Measure) | |
|
|
||||||
| [delay](/api/qiskit/qiskit.circuit.Delay) | |
|
|
||||||
|
|
||||||
<Admonition type="tip" title="The init_qubits flag">
|
|
||||||
|
|
||||||
The `init_qubits` flag, set as a [primitive execution option,](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.ExecutionOptions) controls whether qubits are reset to the zero state at the start of each circuit. Its default value is `True`, indicating that the qubits should be reset. If `False`, the qubits will begin in the final state from the previous shot, and you must manually insert [resets](/api/qiskit/qiskit.circuit.library.Reset) if you want to reset them to the zero state. If a job consists of multiple circuits, then the shots are executed in a "round-robin" fashion. That is, each circuit will be executed in sequence to obtain one shot from each circuit. This process is then repeated until the requested number of shots has been obtained from all circuits.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Read about basis gates in the [Represent quantum computers](../transpile/representing_quantum_computers#basis-gates) topic.
|
|
||||||
- Apply your knowledge of basis gates to one of these [workflow example tutorials.](https://learning.quantum.ibm.com/catalog/tutorials?category=workflow-example)
|
|
||||||
</Admonition>
|
|
|
@ -1,287 +0,0 @@
|
||||||
---
|
|
||||||
title: Primitives examples
|
|
||||||
description: Practical examples of primitive usage
|
|
||||||
---
|
|
||||||
|
|
||||||
# Primitives examples
|
|
||||||
|
|
||||||
The examples in this section illustrate some common ways to use primitives. Before running these examples, follow the instructions in [Install and set up.](../start/install)
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
These examples all use the primitives from Qiskit Runtime, but you could use the base primitives instead.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Estimator examples
|
|
||||||
|
|
||||||
Efficiently calculate and interpret expectation values of the quantum operators required for many algorithms with Estimator. Explore uses in molecular modeling, machine learning, and complex optimization problems.
|
|
||||||
|
|
||||||
### Run a single experiment
|
|
||||||
|
|
||||||
Use Estimator to determine the expectation value of a single circuit-observable pair.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import SparsePauliOp, random_hermitian
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=1234))
|
|
||||||
circuit = IQP(mat)
|
|
||||||
observable = SparsePauliOp("Z" * n_qubits)
|
|
||||||
|
|
||||||
estimator = Estimator(backend)
|
|
||||||
job = estimator.run(circuit, observable)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
print(f" > Observable: {observable.paulis}")
|
|
||||||
print(f" > Expectation value: {result.values}")
|
|
||||||
print(f" > Metadata: {result.metadata}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run multiple experiments in a single job
|
|
||||||
|
|
||||||
Use Estimator to determine the expectation values of multiple circuit-observable pairs.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import SparsePauliOp, random_hermitian
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
|
|
||||||
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
rng = np.random.default_rng()
|
|
||||||
mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]
|
|
||||||
circuits = [IQP(mat) for mat in mats]
|
|
||||||
observables = [
|
|
||||||
SparsePauliOp("X" * n_qubits),
|
|
||||||
SparsePauliOp("Y" * n_qubits),
|
|
||||||
SparsePauliOp("Z" * n_qubits),
|
|
||||||
]
|
|
||||||
|
|
||||||
estimator = Estimator(backend)
|
|
||||||
job = estimator.run(circuits, observables)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
print(f" > Expectation values: {result.values}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run parameterized circuits
|
|
||||||
|
|
||||||
Use Estimator to run three experiments in a single job, leveraging parameter values to increase circuit reusability.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import RealAmplitudes
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
circuit = RealAmplitudes(num_qubits=127, reps=2)
|
|
||||||
# Define three sets of parameters for the circuit
|
|
||||||
rng = np.random.default_rng(1234)
|
|
||||||
parameter_values = [
|
|
||||||
rng.uniform(-np.pi, np.pi, size=circuit.num_parameters) for _ in range(3)
|
|
||||||
]
|
|
||||||
observable = SparsePauliOp("Z" * 127)
|
|
||||||
|
|
||||||
estimator = Estimator(backend)
|
|
||||||
job = estimator.run([circuit] * 3, [observable] * 3, parameter_values)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
print(f" > Expectation values: {result.values}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use sessions and advanced options
|
|
||||||
|
|
||||||
Explore sessions and advanced options to optimize circuit performance on quantum systems.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import SparsePauliOp, random_hermitian
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Estimator, Options
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
rng = np.random.default_rng(1234)
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=rng))
|
|
||||||
circuit = IQP(mat)
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=rng))
|
|
||||||
another_circuit = IQP(mat)
|
|
||||||
observable = SparsePauliOp("X" * n_qubits)
|
|
||||||
another_observable = SparsePauliOp("Y" * n_qubits)
|
|
||||||
|
|
||||||
options = Options()
|
|
||||||
options.optimization_level = 2
|
|
||||||
options.resilience_level = 2
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
with Session(service=service, backend=backend) as session:
|
|
||||||
estimator = Estimator(session=session, options=options)
|
|
||||||
job = estimator.run(circuit, observable)
|
|
||||||
another_job = estimator.run(another_circuit, another_observable)
|
|
||||||
result = job.result()
|
|
||||||
another_result = another_job.result()
|
|
||||||
|
|
||||||
# first job
|
|
||||||
print(f" > Expectation values job 1: {result.values}")
|
|
||||||
|
|
||||||
# second job
|
|
||||||
print(f" > Expectation values job 2: {another_result.values}")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sampler examples
|
|
||||||
|
|
||||||
Generate entire error-mitigated quasi-probability distributions sampled from quantum circuit outputs. Leverage Sampler’s capabilities for search and classification algorithms like Grover’s and QVSM.
|
|
||||||
|
|
||||||
### Run a single experiment
|
|
||||||
|
|
||||||
Use Sampler to determine the quasi-probability distribution of a single circuit.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import random_hermitian
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=1234))
|
|
||||||
circuit = IQP(mat)
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
sampler = Sampler(backend)
|
|
||||||
job = sampler.run(circuit)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
print(f" > Quasi-probability distribution: {result.quasi_dists}")
|
|
||||||
print(f" > Metadata: {result.metadata}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run multiple experiments in a single job
|
|
||||||
|
|
||||||
Use Sampler to determine the quasi-probability distributions of multiple circuits in one job.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import random_hermitian
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
rng = np.random.default_rng()
|
|
||||||
mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]
|
|
||||||
circuits = [IQP(mat) for mat in mats]
|
|
||||||
for circuit in circuits:
|
|
||||||
circuit.measure_all()
|
|
||||||
|
|
||||||
sampler = Sampler(backend)
|
|
||||||
job = sampler.run(circuits)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
print(f" > Quasi-probability distribution: {result.quasi_dists}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run parameterized circuits
|
|
||||||
|
|
||||||
Run three experiments in a single job, leveraging parameter values to increase circuit reusability.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import RealAmplitudes
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
circuit = RealAmplitudes(num_qubits=127, reps=2)
|
|
||||||
circuit.measure_all()
|
|
||||||
# Define three sets of parameters for the circuit
|
|
||||||
rng = np.random.default_rng(1234)
|
|
||||||
parameter_values = [
|
|
||||||
rng.uniform(-np.pi, np.pi, size=circuit.num_parameters) for _ in range(3)
|
|
||||||
]
|
|
||||||
|
|
||||||
sampler = Sampler(backend)
|
|
||||||
job = sampler.run([circuit] * 3, parameter_values)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
print(f" > Quasi-probability distribution: {result.quasi_dists}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use sessions and advanced options
|
|
||||||
|
|
||||||
Explore sessions and advanced options to optimize circuit performance on quantum systems.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import random_hermitian
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Session, Options
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
rng = np.random.default_rng(1234)
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=rng))
|
|
||||||
circuit = IQP(mat)
|
|
||||||
circuit.measure_all()
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=rng))
|
|
||||||
another_circuit = IQP(mat)
|
|
||||||
another_circuit.measure_all()
|
|
||||||
|
|
||||||
options = Options()
|
|
||||||
options.optimization_level = 2
|
|
||||||
options.resilience_level = 0
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
backend = service.get_backend("ibm_brisbane")
|
|
||||||
|
|
||||||
with Session(service=service, backend=backend) as session:
|
|
||||||
sampler = Sampler(session=session, options=options)
|
|
||||||
job = sampler.run(circuit)
|
|
||||||
another_job = sampler.run(another_circuit)
|
|
||||||
result = job.result()
|
|
||||||
another_result = another_job.result()
|
|
||||||
|
|
||||||
# first job
|
|
||||||
print(f" > Quasi-probability distribution job 1: {result.quasi_dists}")
|
|
||||||
|
|
||||||
# second job
|
|
||||||
print(f" > Quasi-probability distribution job 2: {another_result.quasi_dists}")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Specify advanced runtime options.](advanced-runtime-options)
|
|
||||||
- Practice with primitives by working through the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum Learning.
|
|
||||||
</Admonition>
|
|
|
@ -1,142 +0,0 @@
|
||||||
---
|
|
||||||
title: Get started with primitives
|
|
||||||
description: Use Qiskit Runtime Estimator and Sampler
|
|
||||||
---
|
|
||||||
|
|
||||||
# Get started with primitives
|
|
||||||
|
|
||||||
The steps in this topic describes how to set up primitives, explore the options you can use to configure them, then invoke them in a program.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
These examples all use the primitives from Qiskit Runtime, but you could use the base primitives instead.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="start-estimator"></span>
|
|
||||||
## Get started with Estimator
|
|
||||||
|
|
||||||
### 1. Initialize the account
|
|
||||||
|
|
||||||
Since Qiskit Runtime `Estimator` is a managed service, you will first need to initialize your account. You can then select the simulator or real system you want to use to calculate the expectation value.
|
|
||||||
|
|
||||||
Follow the steps in the [Install and set up topic](../start/install) if you don't already have an account.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibm_brisbane")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Create a circuit and an observable
|
|
||||||
|
|
||||||
Just like the section before, you will need at least one circuit and one observable as inputs to the `Estimator` primitive.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import SparsePauliOp, random_hermitian
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=1234))
|
|
||||||
circuit = IQP(mat)
|
|
||||||
observable = SparsePauliOp("Z" * n_qubits)
|
|
||||||
print(f">>> Observable: {observable.paulis}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Initialize the Qiskit Runtime Estimator
|
|
||||||
|
|
||||||
Here we are initializing an instance of `qiskit_ibm_runtime.Estimator` instead of `qiskit.primitives.Estimator` to use Qiskit Runtime's implementation of the `Estimator`.
|
|
||||||
|
|
||||||
When you initialize the `Estimator`, you'll need to pass in the system or simulator you previously selected as the target device (or simulator). You could also do this within the `session` parameter.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Estimator
|
|
||||||
|
|
||||||
estimator = Estimator(backend=backend)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Invoke the Estimator and get results
|
|
||||||
|
|
||||||
You can then invoke the `run()` method to calculate expectation values for the input circuits and observables.
|
|
||||||
|
|
||||||
```python
|
|
||||||
job = estimator.run(circuit, observable)
|
|
||||||
print(f">>> Job ID: {job.job_id()}")
|
|
||||||
print(f">>> Job Status: {job.status()}")
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
result = job.result()
|
|
||||||
print(f">>> {result}")
|
|
||||||
print(f" > Expectation value: {result.values[0]}")
|
|
||||||
print(f" > Metadata: {result.metadata[0]}")
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="start-sampler"></span>
|
|
||||||
## Get started with Sampler
|
|
||||||
|
|
||||||
### 1. Initialize the account
|
|
||||||
|
|
||||||
Since Qiskit Runtime `Sampler` is a managed service, you will first need to initialize your account. You can then select the simulator or real system you want to use to calculate the expectation value.
|
|
||||||
|
|
||||||
Follow the steps in the [Install and set up topic](../start/install) if you don't already have an account set up.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibm_brisbane")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Create a circuit
|
|
||||||
|
|
||||||
Just like the section before, you will need at least one circuit as the input to the `Sampler` primitive.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
from qiskit.circuit.library import IQP
|
|
||||||
from qiskit.quantum_info import random_hermitian
|
|
||||||
|
|
||||||
n_qubits = 127
|
|
||||||
|
|
||||||
mat = np.real(random_hermitian(n_qubits, seed=1234))
|
|
||||||
circuit = IQP(mat)
|
|
||||||
circuit.measure_all()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Initialize the Qiskit Runtime Sampler
|
|
||||||
|
|
||||||
Here we are initializing an instance of `qiskit_ibm_runtime.Sampler` instead of `qiskit.primitives.Sampler` to use Qiskit Runtime's implementation of the `Sampler`.
|
|
||||||
|
|
||||||
When you initialize the `Sampler`, you'll need to pass in the simulator or system you previously selected as the target device (or simulator). You could also do this within the `session` parameter.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Sampler
|
|
||||||
|
|
||||||
sampler = Sampler(backend=backend)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Invoke the Sampler and get results
|
|
||||||
|
|
||||||
You can then invoke the `run()` method to generate a quasi-probability distribution for the input circuits and quantum states.
|
|
||||||
|
|
||||||
```python
|
|
||||||
job = sampler.run(circuit)
|
|
||||||
print(f">>> Job ID: {job.job_id()}")
|
|
||||||
print(f">>> Job Status: {job.status()}")
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
result = job.result()
|
|
||||||
print(f">>> {result}")
|
|
||||||
print(f" > Quasi-probability distribution: {result.quasi_dists[0]}")
|
|
||||||
print(f" > Metadata: {result.metadata[0]}")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Review detailed [primitives examples.](primitives-examples)
|
|
||||||
- Practice with primitives by working through the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum Learning.
|
|
||||||
</Admonition>
|
|
|
@ -1,90 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduction to primitives
|
|
||||||
description: Introduction to primitives in Qiskit and Qiskit Runtime, and an explanation of available primitives
|
|
||||||
---
|
|
||||||
|
|
||||||
# Introduction to primitives
|
|
||||||
|
|
||||||
Computing systems are built upon multiple layers of abstraction. Abstractions allow us to focus on a
|
|
||||||
particular level of detail relevant to the task at hand. The closer you get to the hardware,
|
|
||||||
the lower the level of abstraction you'll need (for example, you could
|
|
||||||
want to manipulate electrical signals), and vice versa, the more complex the task you want to perform,
|
|
||||||
the higher-level the abstractions will be (for example, you could be using a programming library to perform
|
|
||||||
algebraic calculations).
|
|
||||||
|
|
||||||
In this context, a primitive is the smallest processing instruction, the simplest building block from which
|
|
||||||
one can create something useful for a given abstraction level.
|
|
||||||
|
|
||||||
The recent progress in quantum computing has increased the need to work at higher levels of abstraction.
|
|
||||||
As we move towards larger systems and more complex workflows, the focus shifts from interacting with individual
|
|
||||||
qubit signals to viewing quantum devices as systems that perform tasks we need.
|
|
||||||
|
|
||||||
The two most common tasks quantum computers are used for are sampling quantum states and calculating expectation values.
|
|
||||||
These tasks motivated the design of _the first two Qiskit primitives: Sampler and Estimator_.
|
|
||||||
|
|
||||||
In short, the computational model introduced by the Qiskit primitives moves quantum programming one step closer
|
|
||||||
to where classical programming is today, where the focus is less on the hardware details and more on the results
|
|
||||||
you are trying to achieve.
|
|
||||||
|
|
||||||
## Implementation of Qiskit primitives
|
|
||||||
|
|
||||||
The Qiskit primitives are defined by open-source primitive base-classes, from
|
|
||||||
which different providers can derive their own Sampler and Estimator implementations. Among the implementations
|
|
||||||
using Qiskit, you can find reference primitive implementations for local simulation in the `qiskit.primitives` module.
|
|
||||||
Providers like IBM’s Qiskit Runtime enable access to appropriate systems through native implementations of
|
|
||||||
their own primitives.
|
|
||||||
|
|
||||||
## Benefits of Qiskit primitives
|
|
||||||
|
|
||||||
For Qiskit users, primitives allow you to write quantum code for a specific system without having to explicitly
|
|
||||||
manage every detail. In addition, because of the additional layer of abstraction, you may be able to more easily
|
|
||||||
access advanced hardware capabilities of a given provider. For example, with Qiskit Runtime primitives,
|
|
||||||
you can leverage the latest advancements in error mitigation and suppression by toggling options such as
|
|
||||||
`optimization_level` and `resilience_level`, rather than building your own implementation of these techniques.
|
|
||||||
|
|
||||||
For hardware providers, implementing primitives natively means you can provide your users with a more “out-of-the-box”
|
|
||||||
way to access your hardware features. It is therefore easier for your users to benefit from your hardware's
|
|
||||||
best capabilities.
|
|
||||||
|
|
||||||
## Estimator
|
|
||||||
|
|
||||||
The Estimator primitive computes expectation values of observables with respect to states prepared by quantum circuits.
|
|
||||||
The Estimator receives circuit-observable pairs (with the observable expressed as a
|
|
||||||
weighted sum of Pauli operators) as inputs, and returns the computed expectation values per pair, as well as their
|
|
||||||
variances. Different Estimator implementations support various configuration options. The circuits
|
|
||||||
can be parametrized, as long as the parameter values are also provided as input to the primitive.
|
|
||||||
|
|
||||||
## Sampler
|
|
||||||
|
|
||||||
The Sampler primitive samples from the classical output registers resulting from execution of quantum circuits.
|
|
||||||
For this reason, the inputs to the Sampler are (parametrized) quantum circuits, for which it returns the corresponding
|
|
||||||
quasi-probability distributions of sampled bitstrings. Quasi-probability distributions are similar to regular
|
|
||||||
probabilities, except they may include negative values, which can occur when using certain error mitigation techniques.
|
|
||||||
|
|
||||||
## How to use Qiskit primitives
|
|
||||||
|
|
||||||
The `qiskit.primitives` module enables the development of primitive-style quantum programs and was specifically
|
|
||||||
designed to simplify switching between different types of systems. The module provides three separate classes
|
|
||||||
for each primitive type:
|
|
||||||
|
|
||||||
1. `Sampler` and `Estimator`
|
|
||||||
|
|
||||||
These classes are reference implementations of both primitives and use Qiskit’s built-in simulator. They leverage Qiskit’s `quantum_info` module in the background, producing results based on ideal statevector simulations.
|
|
||||||
|
|
||||||
2. `BaseSampler` and `BaseEstimator`
|
|
||||||
|
|
||||||
These are abstract base classes that define a common interface for implementing primitives. All other classes in the `qiskit.primitives` module inherit from these base classes, and developers should use these if they are interested in developing their own primitives-based execution model for a specific system provider. These classes may also be useful for those who want to do highly customized processing and find the existing primitives implementations too simple for their needs.
|
|
||||||
|
|
||||||
3. `BackendSampler` and `BackendEstimator`
|
|
||||||
|
|
||||||
If a provider does not support primitives natively, you can use these classes to “wrap” any system into a primitive. Users can write primitive-style code for providers that don’t yet have a primitives-based interface. These classes can be used just like the regular Sampler and Estimator, except they should be initialized with an additional `backend` argument for selecting which system to run on.
|
|
||||||
|
|
||||||
The Qiskit Runtime primitives provide a more sophisticated implementation (such as with error mitigation) as a cloud-based service.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Read [Get started with primitives](primitives-get-started) to implement primitives in your work.
|
|
||||||
- Review detailed [primitives examples.](primitives-examples)
|
|
||||||
- Practice with primitives by working through the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum Learning.
|
|
||||||
</Admonition>
|
|
|
@ -1,126 +0,0 @@
|
||||||
---
|
|
||||||
title: Processor types
|
|
||||||
description: Information on IBM Quantum hardware and features of different processors
|
|
||||||
---
|
|
||||||
|
|
||||||
# Processor types
|
|
||||||
|
|
||||||
Processor types are named for the general technology qualities that go into builds, consisting of the family and revision. Family (e.g., Falcon) refers to the size and scale of circuits possible on the chip. This is primarily determined by the number of qubits and the connectivity graph. Revisions (e.g., r1) are design variants within a given family, often leading to performance improvements or tradeoffs. Segments are comprised of chip sub-sections, and are defined within a given family. For instance, segment H of a Falcon consists of seven qubits arranged as seen in the illustration below. Segment H on a Hummingbird, if implemented, could be entirely different.
|
|
||||||
|
|
||||||
![Illustration of segment H on a Falcon processor.](/images/run/processor-types/seg-h.png "Illustration of segment H on a Falcon processor")
|
|
||||||
|
|
||||||
## Heron
|
|
||||||
|
|
||||||
![Heron processor icon](/images/run/processor-types/heron.svg)
|
|
||||||
|
|
||||||
Quantum volume: 512
|
|
||||||
|
|
||||||
At 133 qubits, Heron is an [Eagle](#eagle)-sized upgrade to [Egret](#egret) that pulls in substantial innovations in signal delivery that were previously deployed in [Osprey](#osprey). The signals required to enable the fast, high-fidelity two-qubit and single-qubit control are delivered with high-density flex cabling.
|
|
||||||
|
|
||||||
- [View available Heron systems](https://quantum.ibm.com/services/resources?tab=systems&type=Heron)
|
|
||||||
|
|
||||||
- [Native gates and operations](native-gates): `cz, id, delay, measure, reset, rz, sx, x, if_else, for_loop, switch_case`
|
|
||||||
|
|
||||||
## Osprey
|
|
||||||
|
|
||||||
![Osprey processor icon](/images/run/processor-types/osprey.svg)
|
|
||||||
|
|
||||||
Osprey is nearly quadruple the size of Eagle at 433 qubits. The larger chip sizes have required further enhancements to device packaging, as well as custom flex cabling in the cryostat to fit the greater I/O requirements within the same wiring footprint.
|
|
||||||
|
|
||||||
- [View available Osprey systems](https://quantum.ibm.com/services/resources?tab=systems&type=Osprey)
|
|
||||||
|
|
||||||
## Eagle
|
|
||||||
|
|
||||||
![Eagle processor icon](/images/run/processor-types/eagle.svg)
|
|
||||||
|
|
||||||
Quantum volume: 128
|
|
||||||
|
|
||||||
At 127 qubits, the Eagle processor family incorporates more scalable packaging technologies than previous generations. In particular, signals pass through multiple chip layers so as to allow for high-density I/O without sacrificing performance.
|
|
||||||
|
|
||||||
See [this blog post](https://research.ibm.com/blog/127-qubit-quantum-processor-eagle) for more about the Eagle processor family.
|
|
||||||
|
|
||||||
- [View available Eagle systems](https://quantum.ibm.com/services/resources?tab=systems&type=Eagle)
|
|
||||||
|
|
||||||
- [Native gates and operations](native-gates): `ecr, id, delay, measure, reset, rz, sx, x, if_else, for_loop, switch_case`
|
|
||||||
|
|
||||||
<Admonition type="info" title="Revisions">
|
|
||||||
`r3` (December 2022) Eagle r3 is a version of the 127-qubit processor with enhanced coherence properties but otherwise similar design parameters to Eagle r1.
|
|
||||||
|
|
||||||
`r1` (December 2021) At the qubit level, Eagle r1 uses similar design elements and parameters to Falcon r5.11, enabling similarly fast readout. Gate speeds and error rates should also be similar.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Hummingbird
|
|
||||||
|
|
||||||
![Hummingbird processor icon](/images/run/processor-types/hummingbird.svg)
|
|
||||||
|
|
||||||
Quantum volume: 128
|
|
||||||
|
|
||||||
Using a heavy-hexagonal qubit layout, the Hummingbird family allows up to 65 qubits.
|
|
||||||
|
|
||||||
- [View available Hummingbird systems](https://quantum.ibm.com/services/resources?tab=systems&type=Hummingbird)
|
|
||||||
|
|
||||||
<Admonition type="info" title="Revisions">
|
|
||||||
`r3` (December 2021) This version of Hummingbird with 65 qubits has enhanced coherence properties.
|
|
||||||
|
|
||||||
`r2` (August 2020) Released in 3Q 2020, this revision contains 65 qubits. Improvements previously demonstrated on Falcons, like readout multiplexing, space-efficient qubit-qubit couplers, and flip-chip technology enhanced the capabilities of the Hummingbird family and led to a scalable 65Q design.
|
|
||||||
|
|
||||||
`r1` (October 2019) This revision is the first attempt at supporting a large (>50) number of qubits on a chip.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Egret
|
|
||||||
|
|
||||||
![Egret processor icon](/images/run/processor-types/egret.svg)
|
|
||||||
|
|
||||||
Quantum volume: 512
|
|
||||||
|
|
||||||
Egret brings the innovations of tunable couplers onto a 33-qubit platform, resulting in faster and higher-fidelity two-qubit gates.
|
|
||||||
|
|
||||||
- [View available Egret systems](https://quantum.ibm.com/services/resources?tab=systems&type=Egret)
|
|
||||||
|
|
||||||
<Admonition type="info" title="Revisions">
|
|
||||||
`r1` (December 2022) The first realization of the Egret processor has demonstrated the highest Quantum Volume among IBM Quantum systems and a substantial improvement in two-qubit gate error rates ([https://research.ibm.com/blog/quantum-volume-256](https://research.ibm.com/blog/quantum-volume-256)). This new quantum processor boasts a substantial speedup and fidelity improvement (many gates approaching 99.9%) in two-qubit gates while reducing spectator errors.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Falcon
|
|
||||||
|
|
||||||
![Falcon processor icon](/images/run/processor-types/falcon.svg)
|
|
||||||
|
|
||||||
Quantum volume: 128
|
|
||||||
|
|
||||||
The Falcon family of devices offers a valuable platform for medium-scale circuits, and also serves as a valuable platform for demonstrating performance and scalability improvements before they’re pushed onto the larger devices.
|
|
||||||
|
|
||||||
- [View available Falcon systems](https://quantum.ibm.com/services/resources?tab=systems&type=Falcon)
|
|
||||||
|
|
||||||
- [Native gates and operations](native-gates): `cx, id, delay, measure, reset, rz, sx, x, if_else, for_loop, switch_case`
|
|
||||||
|
|
||||||
<Admonition type="info" title="Revisions">
|
|
||||||
`r8` (September 2021) In addition to the features of r5.11, Falcon r8 has enhanced coherence properties.
|
|
||||||
|
|
||||||
`r5.11` (January 2021) In addition to the filtering in r5.10, design improvements target speed-ups in qubit state readout. An essential requirement for quantum error correction demonstrations is fast readout. To enable this, the paradoxical requirements of stronger readout coupling yet protection from qubit relaxation is accomplished with advanced filtering techniques and fine tuning of various components’ couplings on-chip. This revision, combined with the latest in control electronics, enables mid-circuit measurements.
|
|
||||||
|
|
||||||
`r5.10` (December 2020) This revision pioneered advanced on-chip filtering techniques that eventually led to the faster qubit state readout in r5.11. The filters reduce qubit relaxation and preserve lifetime. Additionally, space-saving “direct-couplers” are used to couple qubits together, essential for scaling to larger bird families.
|
|
||||||
|
|
||||||
`r4` (April 2020) Adding to the capabilities of r1, the r4 is the first revision in the large birds to deploy multiplexed readout. Previous designs required an independent signal pathway on the chip, as well as in the dilution refrigerator and control electronics for qubit state readout.
|
|
||||||
|
|
||||||
`r1` (February 2020) The first generation of the Falcon family, r1 is a 28Q offering independent readout, contrasting to the multiplexed configurations in the other revisions. The flip-chip technology allowed scaling to a larger number of qubits. The heavy-hex connectivity graph is employed for the first time here, optimal for our two-qubit gate of choice, cross-resonance.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Canary
|
|
||||||
|
|
||||||
![Canary processor icon](/images/run/processor-types/canary.svg)
|
|
||||||
|
|
||||||
The Canary family comprises small designs containing anywhere from 5 to 16 qubits. It uses an optimized 2D lattice. That is, all of the qubits and readout resonators are on the same layer.
|
|
||||||
|
|
||||||
- [View available Canary systems](https://quantum.ibm.com/services/resources?tab=systems&type=Canary)
|
|
||||||
|
|
||||||
<Admonition type="info" title="Revisions">
|
|
||||||
`r1.3` (December 2019) A stripped-down offering containing only a single qubit.
|
|
||||||
|
|
||||||
`r1.1` (May 2017) Using the similar design processes to r1, r1.1 extends the design to include 16 qubits.
|
|
||||||
|
|
||||||
`r1` (January 2017) Initial 5Q design with resonators and qubits all on a single lithography layer.
|
|
||||||
|
|
||||||
</Admonition>
|
|
|
@ -1,167 +0,0 @@
|
||||||
---
|
|
||||||
title: Run workloads remotely with Quantum Serverless
|
|
||||||
description: Run workloads remotely with Quantum Serverless
|
|
||||||
---
|
|
||||||
|
|
||||||
# Run workloads remotely with Quantum Serverless
|
|
||||||
|
|
||||||
Premium users can build, deploy, and run their workloads remotely on classical compute made available through the IBM Quantum Platform.
|
|
||||||
|
|
||||||
Try out the tutorials in [IBM Quantum Learning](https://learning.quantum.ibm.com/catalog/tutorials?topics=qiskit-patterns) (note: these are accessible in the Premium Plan once you have logged into your IBM Quantum account) and explore more of the features of Quantum Serverless in the [documentation](https://qiskit-extensions.github.io/quantum-serverless/).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
This is an experimental feature, subject to change.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Qiskit Patterns with Quantum Serverless
|
|
||||||
|
|
||||||
Creating utility-scale quantum applications generally requires a variety of compute resource requirements. You can use Quantum Serverless to easily submit quantum workflows for remote, managed execution. These quantum workflows can typically be implemented within a common pattern, called a Qiskit Pattern. A Qiskit Pattern is an intuitive, repeatable set of steps for implementing a quantum computing workflow.
|
|
||||||
|
|
||||||
Steps in a Qiskit Pattern:
|
|
||||||
|
|
||||||
1. Map classical inputs to a quantum problem
|
|
||||||
2. Optimize problem for quantum execution
|
|
||||||
3. Execute using Qiskit Runtime primitives
|
|
||||||
4. Post-process, return result in classical format
|
|
||||||
|
|
||||||
Once you have built a Qiskit Pattern, you can use Quantum Serverless to deploy it and submit it for managed execution. Overall, the process of creating quantum software and submitting it for managed execution on a remote cluster can be broken down into three steps:
|
|
||||||
|
|
||||||
1. Build the Qiskit Pattern
|
|
||||||
2. Deploy to the Quantum Serverless
|
|
||||||
3. Run remotely on Quantum Serverless
|
|
||||||
|
|
||||||
## Build a Qiskit Pattern
|
|
||||||
|
|
||||||
Here is an example of computing the expectation value using the Qiskit Runtime Estimator primitive. This Python script should be saved in your working directory. (Warning! All contents of the working directory will be shipped to the cluster for execution.)
|
|
||||||
|
|
||||||
```python
|
|
||||||
# source_files/my_qiskit_pattern.py
|
|
||||||
|
|
||||||
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
|
||||||
from qiskit.circuit.random import random_circuit
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
|
|
||||||
from quantum_serverless import save_result
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.least_busy(simulator=False)
|
|
||||||
|
|
||||||
# Step 1: Map quantum circuits and operators
|
|
||||||
abstract_circuit = random_circuit(2, 2, seed=1234)
|
|
||||||
observable = SparsePauliOp("IY")
|
|
||||||
|
|
||||||
# Step 2: Optimize the circuit for quantum execution
|
|
||||||
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
|
|
||||||
target_circuit = pm.run(abstract_circuit)
|
|
||||||
target_observable = observable.apply_layout(target_circuit.layout)
|
|
||||||
|
|
||||||
# Step 3: Execute the target circuit
|
|
||||||
estimator = Estimator(backend)
|
|
||||||
job = estimator.run(target_circuit, target_observable)
|
|
||||||
result = job.result()
|
|
||||||
|
|
||||||
# Step 4: Postprocess the results
|
|
||||||
print(result)
|
|
||||||
|
|
||||||
# save results of program execution
|
|
||||||
# note: saved items must be serializable
|
|
||||||
save_result(result.values)
|
|
||||||
```
|
|
||||||
|
|
||||||
Please refer to our guides on how to configure your pattern to [accept input arguments](https://qiskit-extensions.github.io/quantum-serverless/getting_started/basic/02_arguments_and_results.html) and [handle external python dependencies](https://qiskit-extensions.github.io/quantum-serverless/getting_started/basic/03_dependencies.html).
|
|
||||||
|
|
||||||
After creating a workflow, authenticate to the `IBMServerlessProvider` with your IBM Quantum token, which can be obtained from your [IBM Quantum account](https://quantum.ibm.com/account), and upload the script.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Authenticate to the IBM serverless provider
|
|
||||||
from quantum_serverless import IBMServerlessProvider
|
|
||||||
serverless = IBMServerlessProvider("YOUR_IBM_QUANTUM_TOKEN")
|
|
||||||
|
|
||||||
# Deploy the pattern
|
|
||||||
from quantum_serverless import QiskitPattern
|
|
||||||
serverless.upload(
|
|
||||||
QiskitPattern(
|
|
||||||
title="My-Qiskit-Pattern",
|
|
||||||
entrypoint="my_qiskit_pattern.py",
|
|
||||||
working_dir="./source_files/"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run a Qiskit Pattern remotely on Quantum Serverless
|
|
||||||
|
|
||||||
Finally, the pattern is ready to run remotely.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Run pattern remotely
|
|
||||||
job = serverless.run("My-Qiskit-Pattern")
|
|
||||||
|
|
||||||
# Retrieve status, logs, results
|
|
||||||
job.status()
|
|
||||||
job.logs()
|
|
||||||
job.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Migration guide
|
|
||||||
|
|
||||||
Qiskit Runtime custom programs can be easily migrated to Quantum Serverless via this [migration guide](https://qiskit-extensions.github.io/quantum-serverless/migration/migration_from_qiskit_runtime_programs.html).
|
|
||||||
|
|
||||||
## Resource management (alpha)
|
|
||||||
|
|
||||||
Premium Plan users have access to an alpha release of resource management functionality through Quantum Serverless. This enables automatic selection of quantum hardware for your workloads.
|
|
||||||
|
|
||||||
The example below demonstrates how to use `IBMQPUSelector` to automate the process of selecting which qubits will be used from a set of available systems. This illustrates how the selectors can be used within a four-step Qiskit Pattern.
|
|
||||||
|
|
||||||
Instead of manually selecting a system, step 2 of the Qiskit Pattern optimizes the circuits for execution by using the QPU selectors from Quantum Serverless to automatically allocate a system according to desired criteria. Here, `IBMLeastNoisyQPUSelector` finds the system, among the ones available to you through your IBM Quantum account, that yields the least-noisy qubit subgraph for the input circuit. You can also use the `IBMLeastBusyQPUSelector` to find a system that can support the circuit width but with the shortest queue.
|
|
||||||
|
|
||||||
For each `IBMQPUSelector`, the context is set in the constructor. All `IBMQPUSelectors` require Qiskit Runtime credentials. The `IBMLeastNoisyQPUSelector` requires a circuit and transpile options specifying how the circuit should be optimized for each system when determining the most optimal QPU and qubit layout. All `IBMQPUSelector`s implement a `get_backend` method, which retrieves the optimal system with respect to the given context. The `get_backend` method also allows for additional filtering of the systems. It is implemented using the same interface as the [QiskitRuntimeService.backends method](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#backends).
|
|
||||||
|
|
||||||
Then, in step 3 of the pattern, you execute the target circuit on the system chosen by the selector. Since you optimized your circuit for the system in step 2, you can skip transpilation in the primitives by setting `skip_transpilation=True`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# source_files/my_qiskit_pattern_resource_management.py
|
|
||||||
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Options
|
|
||||||
from qiskit.circuit.random import random_circuit
|
|
||||||
from quantum_serverless_tools.selectors import IBMLeastNoisyQPUSelector
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
# Step 1: Map quantum circuits and operators
|
|
||||||
abstract_circuit = random_circuit(
|
|
||||||
num_qubits=5, depth=4, measure=True, seed=1234
|
|
||||||
)
|
|
||||||
|
|
||||||
# Step 2: Optimize the circuit for quantum execution with automatically selected system
|
|
||||||
selector = IBMLeastNoisyQPUSelector(
|
|
||||||
service, circuit=abstract_circuit, transpile_options={"optimization_level": 3}
|
|
||||||
)
|
|
||||||
backend = selector.get_backend(min_num_qubits=127)
|
|
||||||
target_circuit = selector.optimized_circuit
|
|
||||||
|
|
||||||
## Alternatively, one can automatically select a system according to most available:
|
|
||||||
# from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
|
||||||
# from quantum_serverless_tools.selectors import IBMLeastBusyQPUSelector
|
|
||||||
#
|
|
||||||
# backend = IBMLeastBusyQPUSelector(service).get_backend(min_num_qubits=127)
|
|
||||||
# pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
|
|
||||||
# target_circuit = pm.run(abstract_circuit)
|
|
||||||
|
|
||||||
# Step 3: Execute the target circuit
|
|
||||||
with Session(service, backend=backend) as session:
|
|
||||||
sampler = Sampler(
|
|
||||||
options=Options(
|
|
||||||
execution={"shots": 1024}, transpilation={"skip_transpilation": True}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
result = sampler.run(target_circuit).result().quasi_dists[0]
|
|
||||||
|
|
||||||
# Step 4: Postprocess the results
|
|
||||||
print(result)
|
|
||||||
|
|
||||||
# save results of program execution
|
|
||||||
# note: saved items must be serializable
|
|
||||||
save_result(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
After creating this pattern, you can deploy and run it remotely with Quantum Serverless as described above.
|
|
|
@ -1,39 +0,0 @@
|
||||||
---
|
|
||||||
title: Reserve system time
|
|
||||||
description: Reserve time on a system as an IBM Quantum Network member
|
|
||||||
---
|
|
||||||
|
|
||||||
# Reserve system time
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Important">
|
|
||||||
This feature is available only to organizations that belong to the [IBM Quantum Network](https://www.ibm.com/quantum/network). Educators and researchers can also make reservations and access other benefits by signing up for one of the special programs we offer. Go to the [Educators program sign-up form](https://quantum.ibm.com/programs/educators) or the [Researchers program sign-up form](https://quantum.ibm.com/programs/researchers) for more information.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Under standard operating conditions, IBM Quantum systems accept jobs according to the dynamic priority assigned by the [fair-share queuing system](fair-share-queue).
|
|
||||||
|
|
||||||
![A job enters the queue and joins other jobs from various instances. The job that entered the queue first exits the queue and is sent to a backend.](/images/run/normal_queue_with_providers1.jpg "Normal device-queuing operation")
|
|
||||||
|
|
||||||
While this system attempts to balance workloads for the benefit of all users, there are often use cases where you may require limited-time access at a higher priority level. IBM Quantum provides an option to gain elevated access to specific systems over a specified period of time: **Dedicated mode**. Depending on your hub configuration, if you are a hub admin or group admin, you can reserve time in advance on a particular system with the **Systems Reservations** tool.
|
|
||||||
|
|
||||||
Example use cases for dedicated mode include the following:
|
|
||||||
|
|
||||||
- In-class demonstrations
|
|
||||||
- Iterative and near-time compute algorithms
|
|
||||||
- Jobs involving detailed noise analysis
|
|
||||||
- Time-critical projects
|
|
||||||
|
|
||||||
<Admonition type="info" title="System reservations and fair-share allocation">
|
|
||||||
System time accumulated while using system reservations counts toward an instance’s fair-share allocation amount.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
If you need sole access to a specific quantum system for a given instance, select dedicated mode when making a reservation (only available to members of the [IBM Quantum Network](https://www.ibm.com/quantum/network)).
|
|
||||||
|
|
||||||
![A job enters the queue and joins other jobs from various instances. The jobs that are sent from Instance 2 are all processed in their own dedicated queue while jobs from other instances wait in the normal queue.](/images/migration/dedicated_queue1.jpg "Instance #2 in dedicated mode")
|
|
||||||
|
|
||||||
The standard fair-share queue is always blocked when the device is in dedicated mode.
|
|
||||||
|
|
||||||
![A job enters the queue and joins other jobs from various instances. There are no jobs from Instance 2. Because the backend is in dedicated mode for instance 2, no jobs are processed. All jobs wait in the normal queue.](/images/migration/dedicated_queue_no_jobs1.jpg "Dedicated mode with no dedicated jobs")
|
|
||||||
|
|
||||||
Dedicated mode with no dedicated jobs from instance #2 leaves the device idle.
|
|
||||||
|
|
||||||
This allows users to implement algorithms where input circuits are conditioned on previous results, such as iterative and near-time compute methods, without having to wait for other users’ results to process. If the dedicated instance has multiple users, then a single user’s jobs may be queued behind those of other users in the instance, as the execution is first-in first-out.
|
|
|
@ -1,92 +0,0 @@
|
||||||
---
|
|
||||||
title: Retired systems
|
|
||||||
description: A list of IBM Quantum systems that are now retired
|
|
||||||
---
|
|
||||||
|
|
||||||
# Retired systems
|
|
||||||
|
|
||||||
The following IBM Quantum® systems have been retired. For the full list of available systems, see the [Compute resources page.](https://quantum.ibm.com/services/resources?services=systems) By default, the information is shown in the card view, but you can use the view switchers (![view-switcher icon](/images/run/view-switcher1.png)) at the top right to change to a sortable table view.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
To retrieve jobs from a retired system, see [these instructions.](#retrieve)
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
| System name | Qubit count | Retirement date (Year - month - day) |
|
|
||||||
| ----------------- | ----------- | ------------------------------------ |
|
|
||||||
| ibm_ithaca | **65** | 2024-01-24 |
|
|
||||||
| ibm_nairobi | **7** | 2023-11-28 |
|
|
||||||
| ibm_lagos | **7** | 2023-11-28 |
|
|
||||||
| ibm_perth | **7** | 2023-11-28 |
|
|
||||||
| ibm_auckland | **27** | 2023-11-09 |
|
|
||||||
| ibmq_guadalupe | **16** | 2023-10-27 |
|
|
||||||
| ibmq_lima | **5** | 2023-09-26 |
|
|
||||||
| ibmq_belem | **5** | 2023-09-26 |
|
|
||||||
| ibmq_quito | **5** | 2023-09-26 |
|
|
||||||
| ibmq_manila | **5** | 2023-09-26 |
|
|
||||||
| ibmq_jakarta | **7** | 2023-09-26 |
|
|
||||||
| ibm_seattle | **433** | 2023-09-07 |
|
|
||||||
| ibm_washington | **127** | 2023-06-03 |
|
|
||||||
| ibmq_oslo | **7** | 2023-05-04 |
|
|
||||||
| ibmq_geneva | **27** | 2023-05-04 |
|
|
||||||
| ibmq_montreal | **27** | 2023-04-11 |
|
|
||||||
| ibmq_toronto | **27** | 2023-04-11 |
|
|
||||||
| ibmq_armonk | **1** | 2022-07-07 |
|
|
||||||
| ibmq_brooklyn | **65** | 2022-06-28 |
|
|
||||||
| ibmq_bogota | **5** | 2022-06-17 |
|
|
||||||
| ibmq_santiago | **5** | 2022-06-17 |
|
|
||||||
| ibmq_casablanca | **7** | 2022-03-02 |
|
|
||||||
| ibmq_sydney | **27** | 2022-01-11 |
|
|
||||||
| ibmq_dublin | **27** | 2021-11-16 |
|
|
||||||
| ibmq_manhattan | **65** | 2021-09-22 |
|
|
||||||
| ibmq_5_yorktown | **5** | 2021-08-09 |
|
|
||||||
| ibmq_16_melbourne | **15** | 2021-08-09 |
|
|
||||||
| ibmq_paris | **27** | 2021-06-30 |
|
|
||||||
| ibmq_rome | **5** | 2021-06-30 |
|
|
||||||
| ibmq_athens | **5** | 2021-06-30 |
|
|
||||||
| ibmq_berlin | **27** | 2020-12-31 |
|
|
||||||
| ibmq_boeblingen | **20** | 2021-01-31 |
|
|
||||||
| ibmq_ourense | **5** | 2021-01-15 |
|
|
||||||
| ibmq_vigo | **5** | 2021-01-15 |
|
|
||||||
| ibmq_valencia | **5** | 2021-01-15 |
|
|
||||||
| ibmq_rochester | **53** | 2020-10-31 |
|
|
||||||
| ibmq_cambridge | **28** | 2020-10-31 |
|
|
||||||
| ibmq_almaden | **20** | 2020-08-31 |
|
|
||||||
| ibmq_singapore | **20** | 2020-08-31 |
|
|
||||||
| ibmq_johannesburg | **20** | 2020-08-31 |
|
|
||||||
| ibmq_essex | **5** | 2020-08-31 |
|
|
||||||
| ibmq_burlington | **5** | 2020-08-31 |
|
|
||||||
| ibmq_london | **5** | 2020-08-31 |
|
|
||||||
|
|
||||||
<span id="retrieve"></span>
|
|
||||||
## Retrieve a job from a retired system
|
|
||||||
|
|
||||||
To retrieve jobs from a retired system, you can use code similar to this, depending on the provider from which the job was sent:
|
|
||||||
|
|
||||||
### For a job run from IBM Provider
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_provider import IBMProvider
|
|
||||||
|
|
||||||
provider = IBMProvider(instance="hub/group/project")
|
|
||||||
|
|
||||||
#If you want to retrieve a list of jobs
|
|
||||||
jobs = provider.backend.jobs(backend_name=<backend_name>)
|
|
||||||
|
|
||||||
#If you want to retrieve a specific job you have the id for
|
|
||||||
job = provider.backend.retrieve_job(<job_id>)
|
|
||||||
```
|
|
||||||
|
|
||||||
### For a job run from Qiskit Runtime
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
# Load your IBM Quantum account(s). Replace "hub/group/project" with your desired instance
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum", instance="hub/group/project")
|
|
||||||
|
|
||||||
# Retrieve a single job by id
|
|
||||||
job = service.job(<job_id>)
|
|
||||||
|
|
||||||
# Retrieve a batch of jobs. Filtering options can be found in the QiskitRuntimeService.jobs api reference
|
|
||||||
jobs = service.jobs(backend_name=<backend_name>)
|
|
||||||
```
|
|
|
@ -1,37 +0,0 @@
|
||||||
---
|
|
||||||
title: Run jobs in a batch
|
|
||||||
description: How to run jobs in batch mode.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Run jobs in a batch
|
|
||||||
|
|
||||||
Batch mode can shorten processing time if all jobs can be provided at the outset. If you want to submit iterative jobs, use [sessions](sessions) instead. Using batch mode has these benefits:
|
|
||||||
|
|
||||||
- The jobs' classical computation, such as compilation, is run in parallel. Thus, running multiple jobs in a batch is significantly faster than running them serially.
|
|
||||||
- There is no delay between job, which can help avoid drift.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
When batching, jobs are not guaranteed to run in the order they are submitted.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
![This diagram illustrates jobs submitted in a batch. It shows five jobs, numbered 0 through 4, in a queue. The jobs are a mix of Estimator and Sampler.](/images/run/batch.png "Figure 1: Batch execution")
|
|
||||||
|
|
||||||
The following example shows how you can divide up a long list of circuits into multiple jobs and run them as a batch to take advantage of the parallel processing.
|
|
||||||
|
|
||||||
```python
|
|
||||||
jobs = []
|
|
||||||
with Batch(backend) as batch:
|
|
||||||
estimator = Estimator(batch)
|
|
||||||
# calls within this context are part of the batch.
|
|
||||||
for obs_set in observable_sets:
|
|
||||||
jobs.append(estimator.run(circuits, observables=obs_set))
|
|
||||||
```
|
|
||||||
|
|
||||||
For a full example, see the following tutorials:
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try the [CHSH inequality](https://learning.quantum.ibm.com/tutorial/chsh-inequality) tutorial.
|
|
||||||
- Try the [Grover's algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.
|
|
||||||
</Admonition>
|
|
|
@ -1,180 +0,0 @@
|
||||||
---
|
|
||||||
title: Run jobs in a session
|
|
||||||
description: Run a job in a session
|
|
||||||
---
|
|
||||||
|
|
||||||
# Run jobs in a session
|
|
||||||
|
|
||||||
There are several ways to set up and use [sessions](sessions). It is recommended that you do not run a session with a single job in it.
|
|
||||||
|
|
||||||
## Set up to use sessions
|
|
||||||
|
|
||||||
Before starting a session, you must [set up Qiskit Runtime](../start/install) and initialize it as a service:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Estimator
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Open a session
|
|
||||||
|
|
||||||
You can open a runtime session by using the context manager `with Session(...)` or by initializing the `Session`
|
|
||||||
class. The session starts when its first job begins execution.
|
|
||||||
|
|
||||||
<Admonition type="note" title="Important">
|
|
||||||
If the first session job is canceled, subsequent session jobs will all fail.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
**Session class**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import Session, Sampler, Estimator
|
|
||||||
|
|
||||||
session = Session(service=service, backend="ibmq_qasm_simulator")
|
|
||||||
estimator = Estimator(session=session)
|
|
||||||
sampler = Sampler(session=session)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Context manager**
|
|
||||||
|
|
||||||
The context manager automatically opens and closes the session.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend="ibmq_qasm_simulator"):
|
|
||||||
estimator = Estimator()
|
|
||||||
sampler = Sampler()
|
|
||||||
```
|
|
||||||
|
|
||||||
When you start a session, you must specify a system or simulator. This can be done by specifying its name or by passing a `backend` object.
|
|
||||||
|
|
||||||
**Specify a system or simulator by name**
|
|
||||||
|
|
||||||
```python
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
with Session(service=service, backend="ibmq_qasm_simulator"):
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
**Pass a `backend` object**
|
|
||||||
|
|
||||||
```python
|
|
||||||
backend = service.get_backend("ibmq_qasm_simulator")
|
|
||||||
with Session(backend=backend):
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="specify-length"></span>
|
|
||||||
## Session length
|
|
||||||
|
|
||||||
You can define the maximum session timeout with the max_time parameter. This should exceed the longest job's execution time and be within the system's limits.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend=backend, max_time="25m"):
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
There is also an interactive timeout value (ITTL, or interactive time to live) that cannot be configured. If no session jobs are queued within that window, the session is temporarily deactivated. To determine a session's ITTL, follow the instructions in [Determine session details](#session-details) and look for the `interactive_timeout` value.
|
|
||||||
|
|
||||||
<span id="close"></span>
|
|
||||||
## Close a session
|
|
||||||
|
|
||||||
A session automatically closes when it exits the context manager. With qiskit-ibm-runtime 0.13 or later releases, when the session context manager is exited, the session is put into "In progress, not accepting new jobs" status. This means that the session finishes processing all running or queued jobs until the maximum timeout value is reached. After all jobs are completed, the session is immediately closed. This allows the scheduler to run the next job without waiting for the session interactive timeout, thereby reducing the average job queuing time. You cannot submit jobs to a closed session.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend=backend) as session:
|
|
||||||
estimator = Estimator()
|
|
||||||
job1 = estimator.run(...)
|
|
||||||
job2 = estimator.run(...)
|
|
||||||
|
|
||||||
# The session is no longer accepting jobs but the submitted job will run to completion.
|
|
||||||
result = job1.result()
|
|
||||||
result2 = job2.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
If you are not using a context manager, it's good practice to manually close the session once all the necessary results have been retrieved. With qiskit-ibm-runtime 0.13 or later releases, when a session is closed with `session.close()`, it no longer accepts new jobs, but the already submitted jobs will still run until completion and their results can be retrieved. Prior to qiskit-ibm-runtime 0.13, when a session is closed with `session.close()`, any jobs that are already running continue to run, but any queued jobs remaining in the session are put into a failed state.
|
|
||||||
|
|
||||||
```python
|
|
||||||
session = Session(backend=backend)
|
|
||||||
estimator = Estimator(session=session)
|
|
||||||
job1 = estimator.run(...)
|
|
||||||
job2 = estimator.run(...)
|
|
||||||
print(f"Result1: {job1.result()}")
|
|
||||||
print(f"Result2: {job2.result()}")
|
|
||||||
|
|
||||||
# Manually close the session. Running and queued jobs will run to completion.
|
|
||||||
session.close()
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="caution" title="When the root job is canceled">
|
|
||||||
Note that when you cancel the root job in the session (the job which has the same ID as the session), the session closes and fails any remaining queued jobs in the session.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="cancel"></span>
|
|
||||||
## Cancel a session
|
|
||||||
|
|
||||||
Canceling a session immediately closes it, failing all queued jobs and preventing new submission. Use the `session.cancel()` method to cancel a session. Any jobs that are already running continue to run but queued jobs are put into a failed state and no further jobs can be submitted to the session. This is a convenient way to quickly fail all queued jobs within a session.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend=backend) as session:
|
|
||||||
estimator = Estimator()
|
|
||||||
job1 = estimator.run(...)
|
|
||||||
job2 = estimator.run(...)
|
|
||||||
# You can use session.cancel() to fail all pending jobs, for example,
|
|
||||||
# if you realize you made a mistake.
|
|
||||||
session.cancel()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Invoke multiple primitives in a session
|
|
||||||
|
|
||||||
A session can handle multiple primitives, allowing for various operations within a single session. The following example shows how you can create both an instance of the `Sampler` class and one of the `Estimator` class and invoke their `run()` methods within a session.
|
|
||||||
|
|
||||||
````python
|
|
||||||
from qiskit_ibm_runtime import Session, Sampler, Estimator
|
|
||||||
|
|
||||||
with Session(backend=backend):
|
|
||||||
sampler = Sampler()
|
|
||||||
estimator = Estimator()
|
|
||||||
|
|
||||||
result = sampler.run(sampler_circuit).result()
|
|
||||||
print(f">>> Quasi-probability distribution from the sampler job: {result.quasi_dists[0]}")
|
|
||||||
|
|
||||||
result = estimator.run(circuit, observable).result()
|
|
||||||
print(f">>> Expectation value from the estimator job: {result.values[0]}")
|
|
||||||
```
|
|
||||||
<span id="session-status"></span>
|
|
||||||
## Check session status
|
|
||||||
|
|
||||||
You can query a session's status to understand its current state by using `session.status()` or on the Jobs page for your channel.
|
|
||||||
|
|
||||||
Session status can be one of the following:
|
|
||||||
|
|
||||||
- `Pending`: The session has not started or has been deactivated. The next session job needs to wait in the queue like other jobs.
|
|
||||||
- `In progress, accepting new jobs`: The session is active and accepting new jobs.
|
|
||||||
- `In progress, not accepting new jobs`: The session is active but not accepting new jobs. Job submission to the session is rejected, but outstanding session jobs will run to completion. The session is automatically closed once all jobs finish.
|
|
||||||
- `Closed`: The session's maximum timeout value has been reached or the session was explicitly closed.
|
|
||||||
|
|
||||||
<span id="session-details"></span>
|
|
||||||
## Determine session details
|
|
||||||
|
|
||||||
For a comprehensive overview of a session's configuration and status, use the `session.details() method`.
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
|
|
||||||
with Session(service=service, backend="ibmq_qasm_simulator") as session:
|
|
||||||
estimator = Estimator()
|
|
||||||
job = estimator.run(circuit, observable)
|
|
||||||
print(session.details())
|
|
||||||
````
|
|
||||||
|
|
||||||
You can also view session details on the [Quantum Platform Jobs page](https://quantum.ibm.com/jobs) or on the IBM Cloud Jobs page, which you access from your [Instances page](https://cloud.ibm.com/quantum/instances).
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try an example in the [Quantum approximate optimization algorithm (QAOA)](https://learning.quantum.ibm.com/tutorial/quantum-approximate-optimization-algorithm) tutorial.
|
|
||||||
- Review the [Session API](https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session) reference.
|
|
||||||
</Admonition>
|
|
|
@ -1,85 +0,0 @@
|
||||||
---
|
|
||||||
title: Sessions
|
|
||||||
description: An overview of sessions and when to use them.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Introduction to Qiskit Runtime sessions
|
|
||||||
|
|
||||||
A session is a Qiskit Runtime feature that lets you efficiently run multi-job iterative workloads on quantum computers. Using sessions helps avoid delays caused by queuing each job separately, which can be particularly useful for iterative tasks that require frequent communication between classical and quantum resources.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The queuing time does not decrease for the first job submitted within a session. Therefore, a session does not provide any benefits when running a single job. Additionally, sessions do not work on simulators because simulators do not have a queue.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Advantages of using sessions
|
|
||||||
|
|
||||||
There are several benefits to using sessions:
|
|
||||||
|
|
||||||
- Efficiency: Multiple jobs from a single algorithm run can be run sequentially without interruptions.
|
|
||||||
- Flexibility: You can submit jobs, check results, and submit new jobs within an active session without needing to start a new one.
|
|
||||||
|
|
||||||
## How sessions work
|
|
||||||
|
|
||||||
The basic workflow for sessions is as follows:
|
|
||||||
|
|
||||||
1. The first job in a session enters the normal queue.
|
|
||||||
2. When the first job starts running, the _maximum timeout_ clock starts.
|
|
||||||
3. Subsequent jobs within the session are prioritized over others, reducing wait times.
|
|
||||||
4. The _interactive timeout_ runs between the jobs in a session. Every session has an interactive timeout value (ITTL, or interactive time to live). If there are no session jobs queued within the ITTL window, the session is temporarily deactivated and normal job selection resumes. A deactivated session can be resumed for the next job<sup>\*</sup> if the session has not reached its maximum timeout value.
|
|
||||||
5. If the maximum timeout value is reached, the sessions end and any remaining queued jobs fail.
|
|
||||||
|
|
||||||
<video title="A line of users is shown. The one in the current session becomes larger than the rest and has rotating arrows around them, indicating that they are the priority. Boxes (jobs) are seen being sent to the QPU (represented by a chandelier) from the current user. Other users begin to pop up during the animation and their jobs appear beneath them as they wait for the prioritized user's session to end. A progress bar appears above the prioritized user to represent the interactive TTL. After the prioritized user's session finishes, the line moves ahead toward the system, and the next person's jobs can begin processing." className="max-w-auto h-auto" controls>
|
|
||||||
<source src="/videos/run/sessions/demo.mp4" type="video/mp4"></source>
|
|
||||||
</video>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
* The job must go through the normal queue to reactivate the session.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
To find the maximum session timeout value for a session, follow the instructions in [Determine session details](run-jobs-in-session#session-details).
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
There might be a limit imposed on the ITTL value depending on whether your hub is Premium, Open, and so on.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
For instructions to start a session, see [Run a job in a session](run-jobs-in-session).
|
|
||||||
|
|
||||||
<span id="ends"></span>
|
|
||||||
## End a session
|
|
||||||
|
|
||||||
A session can end in the following circumstances:
|
|
||||||
|
|
||||||
- The maximum timeout is reached, resulting in the cancelation of all queued jobs.
|
|
||||||
- The session is manually canceled, resulting in the cancelation of all queued jobs.
|
|
||||||
- The session is manually closed. The session stops accepting new jobs but continues to run queued jobs with priority.
|
|
||||||
|
|
||||||
## Usage patterns
|
|
||||||
|
|
||||||
Sessions run iteratively. This is useful for algorithms that require classical post-processing, where jobs submitted within the interactive time-out are processed immediately. If you want to submit jobs in a batch instead, see [Run jobs in a batch.](run-jobs-batch)
|
|
||||||
|
|
||||||
Example: Run an iterative workload that uses the classical SciPy optimizer to minimize a cost function. In this model, SciPy uses the output of the cost function to calculate its next input.
|
|
||||||
|
|
||||||
```python
|
|
||||||
def cost_func(params, ansatz, hamiltonian, estimator):
|
|
||||||
# Return estimate of energy from estimator
|
|
||||||
|
|
||||||
energy = estimator.run(ansatz, hamiltonian, parameter_values=params).result().values[0]
|
|
||||||
return energy
|
|
||||||
|
|
||||||
x0 = 2 * np.pi * np.random.random(num_params)
|
|
||||||
|
|
||||||
session = Session(backend=backend)
|
|
||||||
|
|
||||||
estimator = Estimator(session=session, options={"shots": int(1e4)})
|
|
||||||
res = minimize(cost_func, x0, args=(ansatz, hamiltonian, estimator), method="cobyla")
|
|
||||||
|
|
||||||
# Close the session because we didn't use a context manager.
|
|
||||||
session.close()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Try an example in the [Quantum approximate optimization algorithm (QAOA)](https://learning.quantum.ibm.com/tutorial/quantum-approximate-optimization-algorithm) tutorial.
|
|
||||||
- Review the [Session API](https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session) reference.
|
|
||||||
</Admonition>
|
|
|
@ -1,101 +0,0 @@
|
||||||
---
|
|
||||||
title: System information
|
|
||||||
description: Information about IBM Quantum system calibration, properties, and versioning
|
|
||||||
---
|
|
||||||
|
|
||||||
# System information
|
|
||||||
|
|
||||||
IBM Quantum offers both open and premium access to a wide variety of quantum systems. All quantum systems deployed by IBM Quantum are based on superconducting qubit technology, as the control and scalability of this technology pave a clear path to achieving quantum advantage with these systems. You can see the full details of all IBM Quantum systems on the [Compute resources page.](https://quantum.ibm.com/services/resources?tab=systems)
|
|
||||||
|
|
||||||
Note that the words "system" and "backend" are often used interchangeably.
|
|
||||||
|
|
||||||
## System versioning
|
|
||||||
|
|
||||||
Each system has a version number in the form X.Y.Z (major.minor.revision). A circuit compiled for a given system version number is guaranteed to run on that system. If the revision number changes, the circuit will continue to run. If the major or minor number changes, the circuit is not guaranteed to run, although it may do so. The conditions under which a version number may change are listed below:
|
|
||||||
|
|
||||||
### Major version
|
|
||||||
|
|
||||||
The major version will increment for system changes such as:
|
|
||||||
|
|
||||||
- Sample changes.
|
|
||||||
- Major changes to the control electronics.
|
|
||||||
- Moving the system to a new location, if significant behavior changes result.
|
|
||||||
|
|
||||||
### Minor version
|
|
||||||
|
|
||||||
The minor version will increment for changes such as:
|
|
||||||
|
|
||||||
- Warmup / cool-down cycles.
|
|
||||||
- Swapping out some electronics, if the replacement appreciably affects operation.
|
|
||||||
- Changing the direction of a controlled-NOT gate.
|
|
||||||
- Dropping a gate for some duration of time due to calibration issues, and corrections cannot readily be done in software.
|
|
||||||
|
|
||||||
### Revision version
|
|
||||||
|
|
||||||
The revision version number will increment for fixes that do not break the existing compiled circuit. These changes include:
|
|
||||||
|
|
||||||
- Manual calibrations to improve fidelities.
|
|
||||||
- Small electronics changes that don’t affect operation.
|
|
||||||
- System software updates.
|
|
||||||
|
|
||||||
## System configuration values
|
|
||||||
|
|
||||||
The following is a subset of system configuration values available in IBM Quantum and from [Qiskit](/api/qiskit/qiskit.providers.models.BackendConfiguration).
|
|
||||||
|
|
||||||
These values are shown on both the Systems and Simulators tabs of the [Compute resources page](https://quantum.ibm.com/services/resources?services=systems) and the details page for each system.
|
|
||||||
|
|
||||||
- **Name** - The unique name assigned to a specific quantum system or simulator. Systems hosted on IBM Cloud® have names that begin with `ibmq_*` (older systems) or `ibm_*` (newer systems). All quantum systems are given a city name, e.g., `ibmq_johannesburg`. This name does not indicate where the actual quantum system is hosted. They are named after IBM locations around the world.
|
|
||||||
- **Qubits** - The number of qubits in a system. For physical quantum systems, this is the number of physical qubits in the device. For simulators, this number need not be uniquely defined, and instead can depend on the simulation method and/or the amount of memory available.
|
|
||||||
- **EPLG** - Error per layered gate in a chain of 100 qubits. Error per layered gate measures the average gate process error in a layered chain of $N$ qubits ($N$=100 here). It is derived from a similar quantity known as the layer fidelity (LF) where EPLG$\_{100}$ = 1-LF$^{\\frac{1}{99}}$ and layer fidelity is the process fidelity of the layered chain of $N$ qubits. For details, see the paper [Benchmarking quantum processor performance at scale](https://arxiv.org/abs/2311.05933).
|
|
||||||
- **CLOPS** - Circuit layer operations per second, and also known as CLOPS_v, is a measure of how many layers of a Quantum volume circuit (virtual circuit) a QPU (quantum processing unit) can execute per unit of time. Find more information about this metric in the paper [Quality, Speed, and Scale: three key attributes to measure the performance of near-term quantum computers](https://arxiv.org/abs/2110.14108).
|
|
||||||
- **CLOPS_h** -- A measure of how many layers of a 100x100 circuit (hardware-aware circuit) a QPU (quantum processing unit) can execute per unit of time.
|
|
||||||
- **QV** - Quantum volume. This value is another metric for system quality based on passing a fidelity threshold for a set of random, square all-to-all connected circuits. Provided as the peak value measured on a system of devices. For details, see the paper [Validating quantum computers using randomized model circuits](https://arxiv.org/abs/1811.12926).
|
|
||||||
- **Status** - The system status.
|
|
||||||
- **Total pending jobs** - The total number of jobs that you have submitted to this system.
|
|
||||||
- **Processor type** - Reflects the system topology and indicates the approximate qubit count.
|
|
||||||
- **Features** - Additional information about the system, such as whether it can be reserved and whether it supports pulse inputs.
|
|
||||||
|
|
||||||
**Additional information available on the details page for each system**
|
|
||||||
|
|
||||||
To access the details page, click the name of the system on the **Compute resources** page.
|
|
||||||
|
|
||||||
- **Version** - The version number of a system in the form `major.minor.revision`. See [System versioning](#system-versioning) for details on how this number is assigned.
|
|
||||||
|
|
||||||
- **Calibration data** (Available for systems only) - Download the calibration data as a .csv file or click the arrow to display the Topology diagram, Individual qubit readout graph, or the Calibration data table. You can customize the data that is shown, depending on the view you have open. For example, on the Topology diagram, you can choose the data you want to see for connections and qubits. The colored bars associated with the diagram or graph indicate the range that is shown, with the average value marked. The color maximum and minimum change depending on the system.
|
|
||||||
|
|
||||||
> - <span id="coupling-map">**Topology diagram** or **coupling map** </span> - A diagram that indicates the pairs of qubits that support two-qubit gate operations between them. This is also called the coupling map or connectivity. Qubits are represented as circles and the supported two-qubit gate operations are displayed as lines connecting the qubits.
|
|
||||||
> - **Individual qubit properties** - Shows the selected property for each qubit on the system. You can view the frequency, T1, T2, Anharmonicity, probability measurements, error rates, and so on.
|
|
||||||
|
|
||||||
- **Your access instance** - Instances that you can use. Click the arrow on the right to expand or collapse this section. For each instance, you can see the following information:
|
|
||||||
|
|
||||||
- **Max shots** - The maximum number of times you can execute a single circuit on a system. The number of shots taken determines the precision of the output probability distribution over repeated executions.
|
|
||||||
- **Max circuits** - The maximum number of quantum circuits that you can submit to this system at one time.
|
|
||||||
- **Max qubits per pulse gate** - The maximum number of qubit arguments allowed to a gate.
|
|
||||||
- **Max channels per pulse gate** - The maximum number of channels you can refer to within a pulse schedule. Typically each qubit is associated with a drive channel, a measure channel, an acquisition channel, and then auxiliary control channels for things like cross resonance.
|
|
||||||
- **Usage** - Click the link to see the jobs that you have run on this system.
|
|
||||||
|
|
||||||
## View system configuration
|
|
||||||
|
|
||||||
View system configuration values by selecting a system on the [Compute resources page.](https://quantum.ibm.com/services/resources?services=systems) The three tabs in the Calibration data section let you choose how to view the calibration data; the Map view tab is automatically selected.
|
|
||||||
|
|
||||||
### Expanded card for a sample system
|
|
||||||
|
|
||||||
![An expanded card for a sample system.](/images/run/exp-card.png "Expanded card for a sample system")
|
|
||||||
|
|
||||||
### System tabs
|
|
||||||
|
|
||||||
Click the download icon in the upper right of any tab to download a CSV file of calibration data.
|
|
||||||
|
|
||||||
**Graph view tab.**
|
|
||||||
|
|
||||||
![The graph view tab shows the calibration data as a graph.](/images/run/graph-view1.png "Graph view tab")
|
|
||||||
|
|
||||||
**Table view tab**
|
|
||||||
|
|
||||||
![The table view tab shows the calibration information as numerical data.](/images/run/table-view.png "Table view tab")
|
|
||||||
|
|
||||||
## Find system information from other channels
|
|
||||||
|
|
||||||
To find your available systems and simulators on **IBM Cloud**, view the [IBM Cloud Compute resources page.](https://cloud.ibm.com/quantum/resources/your-resources) You must be logged in to see your available compute resources. You are shown a snapshot of each system. To see full details, click the system name. You can also search for systems from this page.
|
|
||||||
|
|
||||||
To find your available systems and simulators on **IBM Quantum Platform**, view the [Platform Compute resources page.](https://quantum.ibm.com/services/resources) You are shown a snapshot of each system. To see full details, click the system name. You can also sort, filter, and search from this page.
|
|
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
"title": "開始",
|
|
||||||
"collapsed": true,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "はじめに",
|
|
||||||
"url": "/start"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "インストール",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Qiskit のインストールとセットアップ",
|
|
||||||
"url": "/start/install"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "IBM 量子チャンネルの選択とセットアップ",
|
|
||||||
"url": "/start/setup-channel"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Hello World",
|
|
||||||
"url": "/start/hello-world"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "高度なセットアップ",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "ソースから Qiskit をインストール",
|
|
||||||
"url": "/start/install-qiskit-source"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Qiskit をローカルで構成",
|
|
||||||
"url": "/start/configure-qiskit-local"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
---
|
|
||||||
title: Qiskit をローカルで構成
|
|
||||||
description: ローカルマシンに Qiskit を構成します
|
|
||||||
---
|
|
||||||
|
|
||||||
# Qiskit をローカルで構成
|
|
||||||
|
|
||||||
Qiskit のインストールと起動が完了したら、Qiskit のデフォルトの動作を変更するために実行できるいくつかのオプションがあります。
|
|
||||||
|
|
||||||
## ユーザー構成ファイル
|
|
||||||
|
|
||||||
Qiskit のローカル構成は主にユーザー構成ファイルで行われます。 これは Qiskit のデフォルトの設定を変更するために使用できる .ini 形式のファイルです。
|
|
||||||
|
|
||||||
例:
|
|
||||||
|
|
||||||
```text
|
|
||||||
[default]
|
|
||||||
circuit_drawer = mpl
|
|
||||||
circuit_mpl_style = default
|
|
||||||
circuit_mpl_style_path = ~:~/.qiskit
|
|
||||||
state_drawer = hinton
|
|
||||||
transpile_optimization_level = 3
|
|
||||||
parallel = False
|
|
||||||
num_processes = 15
|
|
||||||
```
|
|
||||||
|
|
||||||
デフォルトでは、このファイルは `~/.qiskit/settings.conf` にありますが、QISKIT_SETTINGS 環境変数を使ってこのパスを上書きすることができます。
|
|
||||||
|
|
||||||
## 利用可能なオプション
|
|
||||||
|
|
||||||
- `circuit_drawer`: 回路ドロワーのデフォルトのシステムを変更します。 `latex`、`mpl`、`text`、または `latex_source` に設定できます。 出力 kwarg が明示的に設定されていない場合、このドロワーシステムが使用されます。
|
|
||||||
- `circuit_mpl_style`: 回路ドロワーの mpl 出力システムに使用されるデフォルトのスタイルシートです。 有効な値は `default` または `bw` です。
|
|
||||||
- `circuit_mpl_style_path`: mpl 出力モードを使用しているときに、回路ドロワーが JSON スタイルシートを検索するために使用するパス。
|
|
||||||
- `state_drawer`: 状態可視化の描画メソッドのデフォルトシステムを変更するために使用されます。 有効な値は `repr`、`text`、`latex`、`latex_source`、`qsphere`、`hinton`、または `bloch` です。 出力 kwarg が [qiskit.quantum_info.DensityMatrix.draw](../api/qiskit/qiskit.quantum_info.DensityMatrix#densitymatrix) メソッドに明示的に設定されていない場合、指定された出力メソッドが使用されます。
|
|
||||||
- \`transpile_optimization_level: [qiskit.compiler.transpile](../api/qiskit/compiler#circuit-and-pulse-compilation-functions) および [qiskit.execute.execute](../api/qiskit/execute#executing-experiments) のデフォルトの最適化レベルを変更します。 0~3 の整数を指定します。
|
|
||||||
- `parallel`: 並列での実行をサポートする演算で Python マルチプロセッシングが有効であるかどうか。 例えば、複数の [qiskit.circuit.QuantumCircuit](../api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit) オブジェクトのトランスパイル。 この設定は、QISKIT_PARALLEL 環境変数で上書きできます。 ブール値を指定します。
|
|
||||||
- `num_processes`: 並列実行が有効である場合に、並列演算に対して起動する並列プロセスの最大数。 この設定は、QISKIT_NUM_PROCS 環境変数で上書きできます。 0 より大きい整数値を指定します。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
* 回路ドロワーの設定は、[qiskit.circuit.QuantumCircuit.draw](../api/qiskit/qiskit.circuit.QuantumCircuit) および [qiskit.visualization.circuit_drawer](../api/qiskit/qiskit.visualization.circuit_drawer#qiskitvisualizationcircuit_drawer) に適用されます。
|
|
||||||
* 状態可視化の描画メソッドは [qiskit.quantum_info.Statevector.draw](../api/qiskit/qiskit.quantum_info.Statevector#statevector) および [qiskit.quantum_info.DensityMatrix.draw](../api/qiskit/qiskit.quantum_info.Statevector#statevector) です。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## 環境変数
|
|
||||||
|
|
||||||
Qiskit のデフォルトの動作を変更するには、以下の環境変数を設定してください。
|
|
||||||
|
|
||||||
- QISKIT_PARALLEL: Python マルチプロセッシングを有効にし、特定の演算を並列化します。例えば、Qiskit の複数の回路を使ったトランスパイルなどです。 ブール値を指定します。
|
|
||||||
- QISKIT_NUM_PROCS: 並列実行が有効である場合に、並列演算に対して起動する並列プロセスの最大数。 0 より大きい整数値を指定します。
|
|
||||||
- RAYON_NUM_THREADS: Qiskit でマルチスレッド演算を実行するためのスレッド数。 デフォルトでは、マルチスレッドコードは論理 CPU ごとに 1 つのスレッドを起動します。 Qiskit が使用するスレッド数を調整するには、これに整数値を設定します。 例えば、RAYON_NUM_THREADS=4 と設定すると、マルチスレッド関数に 4 つのスレッドが起動します。
|
|
||||||
- QISKIT_FORCE_THREADS: マルチスレッドコードが常に複数のスレッドで実行することを指定します。 デフォルトでは、並列プロセスですでに実行している Qiskit のセクションで祭りスレッドコードを実行している場合、Qiskit は複数のスレッドを起動しない代わりに関数を順次に実行します。 これは、限られた CPU リソースの潜在的なオーバーロードを回避するためです。 ただし、マルチプロセスのコンテキストにおいても複数のスレッドの使用を強制する場合は、QISKIT_FORCE_THREADS=TRUE に設定します。
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [回路を構築](../build/)する方法を学習します。
|
|
||||||
- [Hello World プログラムを実行](hello-world)します。
|
|
||||||
- [Grover's Algorithm(グローバーのアルゴリズム)](https://learning.quantum.ibm.com/tutorial/grovers-algorithm)などのチュートリアルを試します。
|
|
||||||
オープンソースの Qiskit SDK に貢献したい場合は、[貢献ガイドライン](https://github.com/Qiskit/qiskit/blob/main/CONTRIBUTING.md)をお読みください。
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
|
@ -1,51 +0,0 @@
|
||||||
---
|
|
||||||
title: はじめに
|
|
||||||
description: IBM Quantum の入門ドキュメンテーション
|
|
||||||
in_page_toc_max_heading_level: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
# はじめに
|
|
||||||
|
|
||||||
量子コミュニティーは 2016 年以降、クラウドで量子コンピューティングを探求してきました。 現在では、_有用な量子計算を実証する_ことを新しい課題としています。
|
|
||||||
|
|
||||||
ユーザーは IBM Quantum を通じて、作業に使用できる高性能かつ実用規模 (>100 量子ビット) の量子系や、スケーラブルで柔軟な量子ソフトウェアにアクセスすることができます。 無料プランを試すことも、使用量に応じた有料プランまたはプレミアムプランでプログラムを実行することも、量子コンピューティングに関わる有用な作業を今すぐ開始できます。
|
|
||||||
|
|
||||||
ドキュメンテーションの主なセクションは、Qiskit で量子回路と演算子を構築してから、回路の実行用に単純化された Qiskit Runtime primitive インターフェースを使ってトランスパイルと量子系での実行を行うという、一般的な量子ユーザーの作業工程に基づいています。 Qiskit と Qiskit Runtime を併用すると、高度なランタイムコンパイル、エラー抑制、および誤り軽減技法を使用してシームレスに回路を実行できます。
|
|
||||||
|
|
||||||
IBM Quantum をはじめてご利用になる場合は、ここから始めるのが適切です。 このセクションのトピックに従って準備を整えてから、[構築](../build)に進んで最初の量子回路を作成しましょう。 このページの上部にあるタブに従って、セクションを順に進めてください。
|
|
||||||
|
|
||||||
特定の内容をお探しですか?
|
|
||||||
|
|
||||||
- [インストール](install): インストールとセットアップの手順に従って、ツールとプラットフォームの使用を開始します。
|
|
||||||
|
|
||||||
- [構築](../build): primitive および動的回路や中間回路の測定などの高度なメソッドを使って量子回路のデザインと開発を行います。 こちらには、回路ライブラリも用意されています。
|
|
||||||
|
|
||||||
- [トランスパイル](../transpile): 様々なエラー認識レベルを使って、ハードウェアで効率的に実行するように回路のコンパイルと最適化を行います。
|
|
||||||
|
|
||||||
- [検証](../verify): 量子回路を検証して評価します。
|
|
||||||
|
|
||||||
- [実行](../run): セッションなどのジョブ構成オプションを使ってハードウェアで実行します。
|
|
||||||
|
|
||||||
- **API リファレンス**: 上記の API リファレンスドロップダウンメニューから、[Qiskit](/api/qiskit)、[Qiskit Runtime IBM Client](/api/qiskit-ibm-runtime)、[Qiskit IBM Runtime Rest API](/api/runtime/)、および [Qiskit IBM プロバイダー](/api/qiskit-ibm-provider) の API リファレンスをご覧ください。 [エラーコードレジストリー](../errors) も提供されています。
|
|
||||||
|
|
||||||
## コミュニティー
|
|
||||||
|
|
||||||
量子コミュニティーに参加すると、他のユーザーとアイデアを交換しながら、他のユーザーが何に取り組んでいるかを知ることができます。
|
|
||||||
|
|
||||||
- [Slack](https://ibm.co/joinqiskitslack) に参加
|
|
||||||
- [LinkedIn](https://www.linkedin.com/showcase/ibm-quantum/) をフォロー
|
|
||||||
- [GitHub](https://github.com/qiskit) に貢献
|
|
||||||
- [YouTube](https://www.youtube.com/qiskit) および [Medium](https://medium.com/qiskit) を閲覧
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Qiskit のインストールとセットアップ](install)を行います。
|
|
||||||
- [Hello World プログラムを実行](hello-world)します。
|
|
||||||
- IBM Quantum Learning で以下のようなハンズオン形式のチュートリアルを詳しくご覧ください。
|
|
||||||
- [Variational Quantum Eigensolver(変分量子固有ソルバー)](https://learning.quantum.ibm.com/tutorial/variational-quantum-eigensolver)
|
|
||||||
- [Quantum Approximate Optimization Algorithm(量子近似最適化アルゴリズム)](https://learning.quantum.ibm.com/tutorial/quantum-approximate-optimization-algorithm)
|
|
||||||
- [Grover's algorithm(グローバーのアルゴリズム)](https://learning.quantum.ibm.com/tutorial/grovers-algorithm)
|
|
||||||
- [Basics of quantum information(量子情報の基礎)](https://learning.quantum.ibm.com/course/basics-of-quantum-information) コースを受講します。
|
|
||||||
- [IBM Quantum Learning の全チュートリアル](https://learning.quantum.ibm.com/catalog?content=tutorials)のリストを確認します。
|
|
||||||
</Admonition>
|
|
|
@ -1,155 +0,0 @@
|
||||||
---
|
|
||||||
title: ソースから Qiskit をインストール
|
|
||||||
description: Qiskit の開発バージョンのインストール方法を学習します。
|
|
||||||
---
|
|
||||||
|
|
||||||
# ソースから Qiskit および Qiskit Runtime をインストール
|
|
||||||
|
|
||||||
ソースから Qiskit をインストールすることで、Python Package Index(PyPI)リポジトリーのバージョンを使用する代わりに、現在開発中のバージョンにアクセスすることができます。 これにより、Qiskit コードの最新バージョンの検査と拡張をより効果的に行えます。
|
|
||||||
|
|
||||||
## 新しい仮想環境の作成とアクティベート
|
|
||||||
|
|
||||||
1. Python だけがインストールされた最小環境を作ります。
|
|
||||||
|
|
||||||
````
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```shell
|
|
||||||
python3 -m venv /path/to/virtual/environment
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```shell
|
|
||||||
python3 -m venv /path/to/virtual/environment
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```text
|
|
||||||
python3 -m venv c:\path\to\virtual\environment
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
````
|
|
||||||
|
|
||||||
2. 新しい環境をアクティベートします。
|
|
||||||
|
|
||||||
````
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```shell
|
|
||||||
source /path/to/virtual/environment/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```shell
|
|
||||||
source /path/to/virtual/environment/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```text
|
|
||||||
c:\path\to\virtual\environment\Scripts\Activate.ps1
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
````
|
|
||||||
|
|
||||||
## Rust コンパイラーをインストール
|
|
||||||
|
|
||||||
Qiskit をコンパイルするには、Rust コンパイラーがお使いのシステムにインストールされている必要があります。 Rust コンパイラーをインストールするには、クロスプラットフォーム Rust インストーラー [rustup](https://rustup.rs/) か、[別のインストール方法](https://forge.rust-lang.org/infra/other-installation-methods.html)を使用します。
|
|
||||||
|
|
||||||
## Qiskit をインストール
|
|
||||||
|
|
||||||
以下の手順にしたがって、Qiskit をインストールします。
|
|
||||||
|
|
||||||
1. Qiskit リポジトリーをクローンします。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/Qiskit/qiskit.git
|
|
||||||
```
|
|
||||||
|
|
||||||
2. `qiskit` ディレクトリーに変更します。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd qiskit
|
|
||||||
```
|
|
||||||
|
|
||||||
3. (オプション)テストまたはリントチェックを実行する場合は、開発者要件をインストールします。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -r requirements-dev.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
4. `qiskit` をインストールします。
|
|
||||||
|
|
||||||
- **標準インストール**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install .
|
|
||||||
```
|
|
||||||
|
|
||||||
- **編集可能モード**: このモードでは、プロジェクトにコード変更があっても、Qiskit を再インストールする必要がありません。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -e .
|
|
||||||
```
|
|
||||||
|
|
||||||
編集可能モードでは、コンパイルされた拡張機能は最適化なしで _デバッグモード_ にビルドされます。 このため、コンパイル済みのコードの実行時パフォーマンスに影響があります。 最適化を有効にしてコンパイル済みの拡張機能をビルドするには、以下のコマンドを実行して _リリースモード_ でバイナリーをビルドし直します。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python setup.py build_rust --release --inplace
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Qiskit で Rust コードを使用している場合は、ローカル変更を行うたびに拡張コードを再ビルドする必要があります。 編集可能モードでは、Rust 拡張機能はインストールコマンドが実行されるときにのみビルドされるため、Rust コードへのローカルの変更は、`build_rust` を再実行しない限り、インストール済みのパッケージに反映されません(`--release` の有無に関係なく、リリースまたはデバッグモードでビルドするかどうかによって決まります)。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Qiskit Runtime をインストール
|
|
||||||
|
|
||||||
Qiskit Runtime をインストールするには、以下の手順を実行します。
|
|
||||||
|
|
||||||
1. Qiskit Runtime リポジトリーをクローンします。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/Qiskit/qiskit-ibm-runtime.git
|
|
||||||
```
|
|
||||||
|
|
||||||
2. `qiskit_ibm_runtime` ディレクトリーに変更します。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd qiskit_ibm_runtime
|
|
||||||
```
|
|
||||||
|
|
||||||
3. (オプション)テストまたはリントチェックを実行する場合は、開発者要件をインストールします。 グローバルの Python インストールを汚染しないように、[仮想環境](https://docs.python.org/3/library/venv.html)を使用することをお勧めします。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -r requirements-dev.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
4. `qiskit-runtime` をインストールします。 グローバルの Python インストールを汚染しないように、[仮想環境](https://docs.python.org/3/library/venv.html)を使用することをお勧めします。
|
|
||||||
|
|
||||||
- **標準インストール**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install .
|
|
||||||
```
|
|
||||||
|
|
||||||
- **編集可能モード**: このモードでは、プロジェクトにコード変更があっても、Qiskit を再インストールする必要がありません。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -e .
|
|
||||||
```
|
|
||||||
|
|
||||||
編集可能モードでは、コンパイルされた拡張機能は最適化なしで _デバッグモード_ にビルドされます。
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- オープンソースの Qiskit SDK に貢献するには、[貢献ガイドライン](https://github.com/Qiskit/qiskit/blob/main/CONTRIBUTING.md)をお読みください。
|
|
||||||
- [回路を構築](../build/)する方法を学習します。
|
|
||||||
- [Hello World プログラムを実行](hello-world)します。
|
|
||||||
- [Grover's Algorithm(グローバーのアルゴリズム)](https://learning.quantum.ibm.com/tutorial/grovers-algorithm)などのチュートリアルを試します。
|
|
||||||
</Admonition>
|
|
|
@ -1,334 +0,0 @@
|
||||||
---
|
|
||||||
title: インストールとセットアップ
|
|
||||||
description: Qiskit および Qiskit Runtime を様々なオペレーティングシステムにインストールし、セットアップします
|
|
||||||
---
|
|
||||||
|
|
||||||
<span id="qiskit-install"></span>
|
|
||||||
# Qiskit のインストールとセットアップ
|
|
||||||
|
|
||||||
ローカル環境でもクラウド環境でも、すべてのユーザーは最初に Qiskit をインストールする必要があります。 実際のシステムでの実行を希望する場合は、次に、IBM 量子システムにアクセスするために、IBM Quantum Platform か IBM Cloud のいずれかを選択する必要があります。
|
|
||||||
|
|
||||||
<span id="local"></span>
|
|
||||||
## Install and set up Qiskit with the Qiskit Runtime client
|
|
||||||
|
|
||||||
1. Python をインストールします。 Check the "Programming Language" section on the [Qiskit PyPI project page](https://pypi.org/project/qiskit/) to determine which Python versions are supported by the most recent release. ダウンロード手順については、[Python Beginners Guide(Python 初心者ガイド)](https://wiki.python.org/moin/BeginnersGuide/Download) をご覧ください。
|
|
||||||
|
|
||||||
Qiskit と他のアプリケーションを分離するには、[Python 仮想環境](https://docs.python.org/3.10/tutorial/venv.html) を使用することをお勧めします。 また、Qiskit の操作には、[Jupyter](https://jupyter.org/install) 開発環境の使用をお勧めします。
|
|
||||||
|
|
||||||
1. Python だけがインストールされた最小環境を作ります。
|
|
||||||
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```shell
|
|
||||||
python3 -m venv /path/to/virtual/environment
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```shell
|
|
||||||
python3 -m venv /path/to/virtual/environment
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```text
|
|
||||||
python3 -m venv c:\path\to\virtual\environment
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
|
|
||||||
2. 新しい環境をアクティベートします。
|
|
||||||
|
|
||||||
<OperatingSystemTabs>
|
|
||||||
<TabItem value="mac" label="macOS">
|
|
||||||
```shell
|
|
||||||
source /path/to/virtual/environment/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="linux" label="Linux">
|
|
||||||
```shell
|
|
||||||
source /path/to/virtual/environment/bin/activate
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem value="win" label="Windows">
|
|
||||||
```text
|
|
||||||
c:\path\to\virtual\environment\Scripts\Activate.ps1
|
|
||||||
```
|
|
||||||
</TabItem>
|
|
||||||
</OperatingSystemTabs>
|
|
||||||
|
|
||||||
2. [pip をインストール](https://pip.pypa.io/en/stable/installation/) します。
|
|
||||||
|
|
||||||
3. 以下のパッケージをインストールします。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
常に最新のバージョンを維持するには、以下のコマンドを定期的に実行し直すか、[Qiskit リリースノート](../api/qiskit/release-notes) および [Qiskit Runtime リリースノート](../api/qiskit-ibm-runtime/release-notes) を確認してください。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install qiskit
|
|
||||||
```
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install qiskit-ibm-runtime
|
|
||||||
```
|
|
||||||
|
|
||||||
`pip list` を実行して、仮想環境内のアクティブなパッケージを確認します。
|
|
||||||
|
|
||||||
可視化機能や Jupyter Notebook を使用する場合は、可視化サポートを追加して Qiskit をインストールすることをお勧めします。 **zsh ユーザー**は、`'qiskit[visualization]'` を単一引用符で囲む必要があることに注意してください。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install qiskit[visualization]
|
|
||||||
```
|
|
||||||
|
|
||||||
zsh ユーザー:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install 'qiskit[visualization]'
|
|
||||||
```
|
|
||||||
|
|
||||||
ローカルで作業し、Qiskit に組み込まれたシミュレーターを使用する予定である場合は、インストールはこれで完了です。 IBM 量子システムでジョブを実行する場合は、次に[アクセスチャンネルを選択](setup-channel)してセットアップを完了させます。
|
|
||||||
|
|
||||||
## トラブルシューティング
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
Jupyter notebook での "No Module 'qiskit'" エラー
|
|
||||||
</summary>
|
|
||||||
``pip install qiskit`` を使い、Anaconda に仮想環境をセットアップしている場合、
|
|
||||||
Jupyter Notebook でチュートリアルを実行する際に、``No Module 'qiskit'`` エラーが
|
|
||||||
発生する場合があります。 Qiskit のインストールまたは仮想環境のセットアップ
|
|
||||||
を完了していない場合は、[インストール](#qiskit-install) の手順を実行してください。
|
|
||||||
|
|
||||||
このエラーは、Qiskit がインストールされていない環境に Qiskit パッケージ
|
|
||||||
をインポートしようとした場合に発生します。 Jupyter Notebook を Anaconda-Navigator から
|
|
||||||
起動した場合、Jupyter Notebook は仮想環境ではなく
|
|
||||||
ベース(ルート)環境で実行している可能性が
|
|
||||||
あります。 Anaconda-Navigator の **Applications on** ドロップダウンメニューから
|
|
||||||
仮想環境を選択してください。 このメニューには
|
|
||||||
Anaconda 内のすべての仮想環境が表示されるため、
|
|
||||||
Qiskit がインストール済みで Jupyter Notebook を起動できる環境を選択
|
|
||||||
できます。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
インストール中のコンパイルエラー
|
|
||||||
</summary>
|
|
||||||
Qiskit は、``pip install qiskit`` を実行する際に自動的にインストールされる
|
|
||||||
多数のオープンソース Python パッケージに依存しています。 お使いのシステムの
|
|
||||||
プラットフォームと Python バージョンによっては、特定のパッケージから
|
|
||||||
そのシステム用に事前にビルドされたバイナリーが提供されない可能性があります。 Qiskit がサポートしている
|
|
||||||
プラットフォームのリストについては、[オペレーティングシステムのサポート](#operating-system-support) をご覧ください。
|
|
||||||
一部には追加のコンパイラーが必要な場合があります。 プリコンパイルされたバイナリーを
|
|
||||||
使用できない場合、``pip`` はソースからパッケージのコンパイルを試みるため、
|
|
||||||
手動によるインストールが必要な追加の依存関係が必要となる場合が
|
|
||||||
あります。
|
|
||||||
|
|
||||||
`pip install qiskit` の出力に以下のような行が含まれている場合:
|
|
||||||
|
|
||||||
```
|
|
||||||
Failed building wheel for SOME_PACKAGE
|
|
||||||
...
|
|
||||||
build/temp.linux-x86_64-3.5/_openssl.c:498:30: fatal error
|
|
||||||
compilation terminated.
|
|
||||||
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
|
|
||||||
```
|
|
||||||
|
|
||||||
ソースからコンパイルするのに必要なライブラリをインストールする方法について、
|
|
||||||
インストールに失敗したパッケージ(この例では `SOME_PACKAGE`)のドキュメン
|
|
||||||
テーションを確認してください。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<span id="os-support"></span>
|
|
||||||
## オペレーティングシステムのサポート
|
|
||||||
|
|
||||||
Qiskit はできるだけ多くのオペレーティングシステムをサポートすることに努めていますが、利用できるテストリソースとオペレーティングシステムの可用性に制限があるため、すべてのオペレーティングシステムをサポートすることはできません。 Qiskit のオペレーティングシステムのサポートは、それぞれにサポートレベルの異なる 3 つのティアに分けられています。 これらに含まれないオペレーティングシステムについては、Qiskit のインストールはおそらく可能ではありますが、未検証であり、Qiskit(および Qiskit の依存関係)をソースからビルドする必要があります。
|
|
||||||
|
|
||||||
また、Qiskit は CPython のみをサポートしています。 他の Python インタープリターでの実行はサポートされていません。
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
ティア 1
|
|
||||||
</summary>
|
|
||||||
ティア 1 オペレーティングシステムは、提案されるすべての変更が正しく機能することを保証するために、開発プロセスの一環として完全に検証済みです。 プリコンパイルのバイナリーは、リリースプロセスの一環として、ビルドとテストを経て PyPI に公開されています。 通常、機能する Python 環境がインストールされている限り、これらのオペレーティングシステムに Qiskit をインストールできます。それ以上の依存関係をインストールする必要はありません。
|
|
||||||
|
|
||||||
ティア 1 オペレーティングシステム:
|
|
||||||
|
|
||||||
- Linux x86_64([manylinux 2014](https://www.python.org/dev/peps/pep-0599/) パッケージ仕様と互換性のあるディストリビューション)。
|
|
||||||
- macOS x86_64(10.12 以降)
|
|
||||||
- Windows 64 ビット
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
ティア 2
|
|
||||||
</summary>
|
|
||||||
ティア 2 オペレーティングシステムは、開発プロセスの一環として検証されていません。 ただし、プリコンパイルのバイナリーは、リリースプロセスの一環としてビルドとテストを経て PyPI に公開されているため、これらのパッケージは機能する Python 環境だけでインストールできることが期待されています。
|
|
||||||
|
|
||||||
ティア 2 オペレーティングシステム:
|
|
||||||
|
|
||||||
- Linux AArch64([manylinux 2014](https://www.python.org/dev/peps/pep-0599/) パッケージ仕様と互換性のあるディストリビューション)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
ティア 3
|
|
||||||
</summary>
|
|
||||||
ティア 3 オペレーティングシステムは、開発プロセスの一環として検証されていません。 プリコンパイルのバイナリーは、リリースプロセスの一環としてビルドされて PyPI に公開されていますが、検証はされていません。 機能する Python 環境だけではインストールできない可能性があり、インストールプロセスで、C/C++ コンパイラーまたはソースから依存関係をビルドするための追加のプログラムが必要となる場合があります。 これらのオペレーティングシステムのサポートはベストエフォートに限定されています。
|
|
||||||
|
|
||||||
ティア 3 オペレーティングシステム:
|
|
||||||
|
|
||||||
- Linux ppc64le([manylinux 2014](https://www.python.org/dev/peps/pep-0599/) パッケージ仕様と互換性のあるディストリビューション)
|
|
||||||
- Linux s390x([manylinux 2014](https://www.python.org/dev/peps/pep-0599/) パッケージ仕様と互換性のあるディストリビューション)
|
|
||||||
- macOS ARM64(10.15 以降)
|
|
||||||
- Linux i686([manylinux 2014](https://www.python.org/dev/peps/pep-0599/) パッケージ仕様と互換性のあるディストリビューション)
|
|
||||||
- Windows 32 ビット
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Qiskit バージョン管理
|
|
||||||
|
|
||||||
Qiskit のバージョン番号は[セマンティックバージョニング](https://semver.org/)に従います。
|
|
||||||
The version number is comprised of three primary components: the major, minor, and
|
|
||||||
patch versions. For example, in version number `X.Y.Z`, `X` is the major version,
|
|
||||||
`Y` is the minor version, and `Z` is the patch version.
|
|
||||||
|
|
||||||
重大な API の変更は、メジャーバージョンリリースに予約されています。 The **minimum**
|
|
||||||
period between major version releases is one year. Minor versions introduce
|
|
||||||
new features and bug fixes without breaking API compatibility, and are
|
|
||||||
periodically (currently every three months) published for **only** the
|
|
||||||
current major version. Patch versions provide fixes for bugs identified in
|
|
||||||
the most recent minor version of each actively supported release series (that is, the
|
|
||||||
major version). We support at most two release series at a time, which occurs
|
|
||||||
only during the period of overlap following a new major version release,
|
|
||||||
described in more detail below.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary id="release-schedule">
|
|
||||||
Release schedule
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
A tentative release schedule is included below:
|
|
||||||
|
|
||||||
![Tentative Qiskit release schedule](/images/start/install/release_schedule.png)
|
|
||||||
|
|
||||||
For an up-to-date release schedule, refer to the Qiskit Github project's [milestones list](https://github.com/Qiskit/qiskit/milestones), which will always contain the current release plan.
|
|
||||||
|
|
||||||
With the release of a new major version, the previous major version is supported
|
|
||||||
for at least six months; only bug and security fixes are accepted during this time and only patch releases are published for this major version. A final
|
|
||||||
patch version is published when support is dropped, and that release
|
|
||||||
also documents the end of support for that major version series. A longer
|
|
||||||
support window is needed for the previous major version as this gives downstream
|
|
||||||
Qiskit consumers and their users a chance to migrate their code.
|
|
||||||
Downstream libraries that
|
|
||||||
depend on Qiskit should not raise their minimum required Qiskit version to a new
|
|
||||||
major version immediately after its release because the library's user base needs time
|
|
||||||
to migrate to the new API changes. Having an extended support window
|
|
||||||
for the previous major Qiskit version gives downstream projects time to ensure
|
|
||||||
compatibility with the next major version. Downstream projects can provide
|
|
||||||
support for two release series at a time to give their users a migration path.
|
|
||||||
|
|
||||||
For the purposes of semantic versioning, the Qiskit public API is considered
|
|
||||||
any documented module, class, function, or method that is not marked as private
|
|
||||||
(with an underscore `_` prefix). However, there can be explicit exceptions made for
|
|
||||||
specific documented APIs. In such cases, these APIs will be clearly documented
|
|
||||||
as not being considered stable interfaces yet, and a user-visible warning will be
|
|
||||||
actively emitted on any use of these unstable interfaces. Additionally, in some
|
|
||||||
situations, an interface marked as private is considered part of the public
|
|
||||||
API. Typically this only occurs in two cases: either an abstract interface
|
|
||||||
definition where subclasses are intended to override/implement a private method
|
|
||||||
as part of defining an implementation of the interface, or advanced-usage
|
|
||||||
low-level methods that have stable interfaces but are not considered safe to use,
|
|
||||||
as the burden is on the user to uphold the class/safety invariants themselves
|
|
||||||
(the canonical example of this is the `QuantumCircuit._append` method).
|
|
||||||
|
|
||||||
The supported Python versions, minimum supported Rust version (for building
|
|
||||||
Qiskit from source), and any Python package dependencies (including the minimum
|
|
||||||
supported versions of dependencies) used by Qiskit are not part of the backwards
|
|
||||||
compatibility guarantees and may change during any release. Only minor or major
|
|
||||||
version releases will raise minimum requirements for using or building Qiskit
|
|
||||||
(including adding new dependencies), but patch fixes might include support for
|
|
||||||
new versions of Python or other dependencies. Usually the minimum version of a
|
|
||||||
dependency is only increased when older dependency versions go out of support or
|
|
||||||
when it is not possible to maintain compatibility with the latest release of the
|
|
||||||
dependency and the older version.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary id="upgrade-strategy">
|
|
||||||
Upgrade strategy
|
|
||||||
</summary>
|
|
||||||
When a new major version is released, the recommended upgrade path
|
|
||||||
is to first upgrade to the most recent minor version on the previous major
|
|
||||||
version. Shortly before a new major version, a final minor version will
|
|
||||||
be published. This final minor version release `X.Y+1.0.0` is equivalent to
|
|
||||||
`X.Y.0` but with warnings and deprecations for any API changes that are
|
|
||||||
made on the new major version series.
|
|
||||||
|
|
||||||
For example, immediately proceeding the 1.0.0 release, a 0.46.0 release will be
|
|
||||||
published. The 0.46.0 release will be equivalent to the 0.45.0 release but with
|
|
||||||
additional deprecation warnings that document the API changes that were made as
|
|
||||||
part of the 1.0.0 release. This pattern will be used for any future major
|
|
||||||
version releases.
|
|
||||||
|
|
||||||
Qiskit users should first upgrade to this final minor
|
|
||||||
version to see any deprecation warnings and adjust their Qiskit
|
|
||||||
usage before trying a potentially breaking release. The previous
|
|
||||||
major version will be supported for at least six months to give sufficient time
|
|
||||||
to upgrade. A typical pattern to manage this is to pin the maximum version to
|
|
||||||
avoid using the next major release series until you're sure of compatibility.
|
|
||||||
For example, specifying `qiskit<2` in a requirements file when the current
|
|
||||||
major Qiskit version is 1 ensures that you're using a version of Qiskit
|
|
||||||
that doesn't have breaking API changes.
|
|
||||||
|
|
||||||
Capping the version less than the next major version
|
|
||||||
ensures that you see any deprecation warnings before a
|
|
||||||
major version release.
|
|
||||||
Without the cap, `pip` installs
|
|
||||||
the newest version available by default.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary id="pre-releases">
|
|
||||||
Pre-releases
|
|
||||||
</summary>
|
|
||||||
For each minor and major version release, Qiskit publishes pre-releases that
|
|
||||||
are compatible with [PEP440](https://peps.python.org/pep-0440/). Typically
|
|
||||||
these are release candidates of the form `X.Y.0rc1`. The `rc` releases
|
|
||||||
will have a finalized API surface and are used to test a prospective release.
|
|
||||||
|
|
||||||
Note that when one of the PEP440 pre-release suffixes (such as `a`, `b`, or `pre`) are
|
|
||||||
published, it does not have the same guarantees as an `rc` release, and is
|
|
||||||
only a preview release. The API might change between these pre-releases
|
|
||||||
and the final release with that version number. For example, `1.0.0pre1` might have
|
|
||||||
a different final API than `1.0.0`.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary id="post-releases">
|
|
||||||
Post-releases
|
|
||||||
</summary>
|
|
||||||
If there are issues with a release's packaging, a post-release might be
|
|
||||||
issued to correct this. These will follow the form `X.Y.Z.1` where the fourth
|
|
||||||
integer indicates that it is the first post-release of the `X.Y.Z` release.
|
|
||||||
For example, the qiskit-terra (the legacy package name for Qiskit) 0.25.2
|
|
||||||
release had some issue with the sdist package publishing, and a post-release
|
|
||||||
0.25.2.1 was published that corrected this issue. The code was identical, and
|
|
||||||
0.25.2.1 only fixed the packaging issue for the release.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [IBM 量子チャンネルの選択とセットアップ](setup-channel)を行います。
|
|
||||||
- [Qiskit をローカルで構成](configure-qiskit-local)します。
|
|
||||||
- [Hello World](hello-world) の手順に従って、量子プログラムを作成して実行します。
|
|
||||||
- [ワークフローのサンプルチュートリアル](https://learning.quantum.ibm.com/catalog/tutorials?category=workflow-example)の 1 つを試します。
|
|
||||||
</Admonition>
|
|
|
@ -1,197 +0,0 @@
|
||||||
---
|
|
||||||
title: IBM Quantum チャンネルの選択とセットアップ
|
|
||||||
description: Qiskit および Qiskit Runtime ジョブを送信するための IBM Quantum Platform または IBM Cloud 上の IBM Quantum のインストールおよびセットアップ手順
|
|
||||||
---
|
|
||||||
|
|
||||||
# IBM Quantum チャンネルの選択とセットアップ
|
|
||||||
|
|
||||||
IBM 量子システムには、IBM Quantum Platform または IBM Cloud _チャンネル_を使ってアクセスすることができます。 _チャンネル_ とは、IBM Quantum サービスにアクセスするために使用する方法を説明するために使用される用語です。
|
|
||||||
|
|
||||||
### IBM Quantum Platform
|
|
||||||
|
|
||||||
IBM Quantum Platform にはオープン(無料アクセス)プランとプレミアム(エンタープライズサブスクリプション)プランがあります。 詳細は、[IBM Quantum アクセスプラン](https://www.ibm.com/quantum/access-plans)をご覧ください。
|
|
||||||
|
|
||||||
`qiskit-ibm-runtime` クライアントを使ってローカル(お使いのノートパソコンまたはその他のデバイス)でリクエストすることも、[IBM Quantum Lab](https://lab.quantum.ibm.com)(Jupyter Notebook 環境)または [IBM Quantum Composer](https://quantum.ibm.com/composer/files/new)(仮想回路作成ツール)などのクラウド環境を使用することもできます。 ローカル環境からリクエストするには、[Qiskit Runtime Client による Qiskit のインストールとセットアップ](install#local)および[IBM Quantum プラットフォームを使用するためのセットアップ](#iqp)を実行する必要があります。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
[IBM Quantum Lab](https://lab.quantum.ibm.com) と [IBM Quantum Composer](https://quantum.ibm.com/composer/files/new)は自己完結型のツールであり、セットアップは不要です。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
利用可能なプラン:
|
|
||||||
|
|
||||||
- **オープンプラン** - 世界最高の量子システムで、量子回路を無料で実行します(月間最大量子時間は 10 分です)。
|
|
||||||
|
|
||||||
- **プレミアムプラン** - エンタープライズ量子時間サブスクリプションを使用して、世界最高の量子システムで量子回路を実行します。
|
|
||||||
|
|
||||||
### IBM Cloud
|
|
||||||
|
|
||||||
IBM Cloud は、従量課金制のアクセスプランを提供しています。 詳細は、[IBM Quantum アクセスプラン](https://www.ibm.com/quantum/access-plans)をご覧ください。
|
|
||||||
|
|
||||||
IBM Cloud にはライト(無料アクセス)プランと標準(従量課金制アクセス)プランがあります。 詳細は、IBM Cloud の [Qiskit Runtime プラン](https://cloud.ibm.com/docs/quantum-computing?topic=quantum-computing-plans)をご覧ください。
|
|
||||||
|
|
||||||
このチャンネルではクラウドベースの開発環境はサポートされていません。 そのため、[Qiskit と Qiskit Runtime のインストールとセットアップ](install#local)および [IBM Cloud を使用するためのセットアップ](#cloud)が必要となります。
|
|
||||||
|
|
||||||
利用可能なプラン:
|
|
||||||
|
|
||||||
- **標準(従量課金制)プラン** - 世界最高の量子システムで量子回路を実行し、使用した量子時間に対してのみ支払います。
|
|
||||||
|
|
||||||
- **ライトプラン**: 無料のシミュレーターを使用して、量子回路のデバッグと量子回路について学習します。
|
|
||||||
|
|
||||||
<span id="iqp"></span>
|
|
||||||
## IBM Quantum Platform を使用するためのセットアップ
|
|
||||||
|
|
||||||
クラウドベースの IBM 量子システムを使用するには、アクセスするための資格情報が必要です。
|
|
||||||
|
|
||||||
1. ユーザーアカウントをまだお持ちでない場合は、[IBM Quantum ログインページ](https://quantum.ibm.com/login)でアカウントを取得します。ユーザーアカウントは、IBM Quantum サービスにアクセスを提供する 1 つ以上の[インスタンス](../run/instances)(hub / group / project の形式)に関連付けられます。 また、各アカウントには一意のトークンが関連付けられるため、Qiskit から IBM Quantum にアクセスできるようになります。 このセクションの手順では、デフォルトのインスタンスを使用します。 特定のインスタンスを選択するための手順については、[インスタンスへの接続](../run/instances#connect-instance)をご覧ください。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
[IBM Quantum アカウントページ](https://quantum.ibm.com/account)の Instances セクションには、アクセスできるインスタンスがリスト表示されています。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
2. [IBM Quantum アカウントページ](https://quantum.ibm.com/account)から IBM Quantum トークンを取得し、Python を起動します。 例:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python3
|
|
||||||
```
|
|
||||||
|
|
||||||
3. IBM Cloud API キーと CRN を指定して `QiskitRuntimeService` を呼び出し、サービスに対する認証を行います。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(channel="ibm_quantum", token="<MY_IBM_QUANTUM_TOKEN>")
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
また、オプションで `save_account()` メソッドを使うと、後で簡単にアクセスできるように、サービスを初期化する前に資格情報を保存することができます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
# IBM Quantum アカウントを保存し、デフォルトにアカウントに設定します。
|
|
||||||
QiskitRuntimeService.save_account(channel="ibm_quantum", token="<MY_IBM_QUANTUM_TOKEN>", set_as_default=True)
|
|
||||||
|
|
||||||
# 保存した資格情報を読み込みます。
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
```
|
|
||||||
|
|
||||||
- 資格情報をディスクに保存すると、以降で `QiskitRuntimeService()` を使ってアカウントを初期化することができます。 `channel` パラメーターはアカウントタイプを区別します。 チャンネルごとに複数のアカウントを保存している場合は、アカウントを区別できるように `name` パラメーターを使用することを検討してください。
|
|
||||||
- チャンネルごとに複数のアカウントを保存している場合は、アカウントを区別できるように `name` パラメーターを使用することを検討してください。
|
|
||||||
- 資格情報は `$HOME/.qiskit/qiskit-ibm.json` に保存されます。 このファイルを手動で編集しないでください。
|
|
||||||
- 資格情報を保存しない場合は、新しいセッションを開始するたびにその情報を指定する必要があります。
|
|
||||||
- `channel` パラメーターを使うと、様々なアカウントタイプを区別することができます。 アカウントを初期化すると、IBM Quantum Platform と IBM Cloud アカウントの資格情報が保存されている場合のデフォルトのアカウントは IBM Cloud です。
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
アカウントの資格情報はプレーンテキストで保存されるため、信頼できるデバイスを使用している場合にのみ保存するようにしてください。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
別のチャンネルやアカウント名を指定しない場合に使用されるデフォルトのアカウントは IBM Cloud です。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
4. セットアップを検証します。 Sampler を使用して単純な回路を実行し、環境が適切にセットアップされていることを確認します。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
# 空の回路を作成します
|
|
||||||
example_circuit = QuantumCircuit(2)
|
|
||||||
example_circuit.measure_all()
|
|
||||||
|
|
||||||
# QiskitRuntimeService を初期化する際に、過去に資格情報を保存していない場合はその情報を指定する必要があります。
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
job = Sampler(backend).run(example_circuit)
|
|
||||||
print(f"job id: {job.job_id()}")
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="cloud"></span>
|
|
||||||
## IBM Cloud を使用するためのセットアップ
|
|
||||||
|
|
||||||
1. Python を開始します。 例:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python3
|
|
||||||
```
|
|
||||||
|
|
||||||
2. IBM Cloud アカウントをまだお持ちでない場合は、[IBM Cloud 登録ページ](https://cloud.ibm.com/registration)でアカウントをセットアップします。
|
|
||||||
|
|
||||||
3. 必要であれば、サービスインスタンスを作成します。 [IBM Cloud Instances ページ](https://cloud.ibm.com/quantum/instances)を開きます。 1 つ以上のインスタンスが表示される場合は、次の手順に進みます。 そうでない場合は **Create instance** をクリックします。 インスタンスの作成時には、インスタンスに名前やタグを付け、リソースグループを指定し、パフォーマンス戦略を選択することができます。 次に、ページの右下にあるボックスをオンにしてライセンス契約に同意し、**Create** をクリックします。
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
組織の Qiskit Runtime を Cloud にセットアップする必要がある管理者は、[組織向けの Qiskit Runtime の計画](https://cloud.ibm.com/docs/quantum-computing?topic=quantum-computing-quickstart-org)をご覧ください。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
パフォーマンス戦略を選択する際は、2 つのオプションを利用できます。 1 つは IBM(デフォルト)で、もう 1 つは Q-CTRL の戦略です。 IBM のパフォーマンス戦略では、[Qiskit Runtime](../api/qiskit-ibm-runtime) で提供されるすべての標準オプションを活用できますが、Q-CTRL 戦略では自動プリセットが使用されます。 Q-CTRL のオプションの詳細については、[Q-CTRL ドキュメンテーション](https://docs.q-ctrl.com/q-ctrl-embedded)をご覧ください。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
4. アクセス資格情報を見つけます。
|
|
||||||
1. API キーを見つけます。 [API keys ページ](https://cloud.ibm.com/iam/apikeys)から、API キーを表示または作成し、認証に使用できるように安全な場所にコピーします。
|
|
||||||
2. クラウドリソース名(CRN)を見つけます。 [Instances ページ](https://cloud.ibm.com/quantum/instances)を開き、インスタンスをクリックします。 開いたページで、アイコンをクリックして CRN をコピーします。 認証に使用できるように安全な場所に保存してください。
|
|
||||||
|
|
||||||
5. 保存した資格情報または IBM Cloud API キーと CRN を指定して `QiskitRuntimeService` を呼び出し、サービスに対する認証を行います。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
service = QiskitRuntimeService(channel="ibm_cloud", token="<IBM Cloud API key>", instance="<IBM Cloud CRN>")
|
|
||||||
```
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
ステップ 3 で Q-CTRL パフォーマンス管理を含めるようにインスタンスをセットアップした場合は、`QiskitRuntimeService()` を初期化する際に、`channel_strategy="q-ctrl"` 引数を追加する必要があります。 Q-CTRL パフォーマンス管理戦略についての詳細は、[Q-CTRL ドキュメンテーション](https://docs.q-ctrl.com/q-ctrl-embedded)をご覧ください。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
オプションで `save_account()` メソッドを使うと、後で簡単にアクセスできるように、サービスを初期化する前に資格情報を保存することができます。
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
|
|
||||||
# アカウントをディスクに保存します。
|
|
||||||
QiskitRuntimeService.save_account(channel="ibm_cloud", token="<IBM Cloud API key>", instance="<IBM Cloud CRN>", name="<account-name>")
|
|
||||||
|
|
||||||
# 保存された資格情報を読み込みます
|
|
||||||
service = QiskitRuntimeService(name="<account-name>")
|
|
||||||
```
|
|
||||||
|
|
||||||
- 資格情報をディスクに保存すると、以降で `QiskitRuntimeService()` を使ってアカウントを初期化することができます。 `channel` パラメーターはアカウントタイプを区別します。 アカウントを初期化すると、IBM Quantum Platform と IBM Cloud アカウントの両方の資格情報が保存されている場合のデフォルトのアカウントは IBM Cloud です。
|
|
||||||
- チャンネルごとに複数のアカウントを保存している場合は、アカウントを区別できるように `name` パラメーターを使用することを検討してください。
|
|
||||||
- 資格情報は `$HOME/.qiskit/qiskit-ibm.json` に保存されます。 このファイルを手動で編集しないでください。
|
|
||||||
- 資格情報を保存しない場合は、新しいセッションを開始するたびにその情報を指定する必要があります。
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
アカウントの資格情報はプレーンテキストで保存されるため、信頼できるデバイスを使用している場合にのみ保存するようにしてください。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
6. セットアップを検証します。 Sampler を使用して単純な回路を実行し、環境が適切にセットアップされていることを確認します。
|
|
||||||
|
|
||||||
````python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
|
|
||||||
|
|
||||||
# 空の回路を作成します
|
|
||||||
example_circuit = QuantumCircuit(2)
|
|
||||||
example_circuit.measure_all()
|
|
||||||
|
|
||||||
# QiskitRuntimeService を初期化する際に、過去に資格情報を保存していない場合はその情報を指定する必要があります。
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.backend("ibmq_qasm_simulator")
|
|
||||||
job = Sampler(backend).run(example_circuit)
|
|
||||||
print(f"job id: {job.job_id()}")
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 次のステップ
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- [Qiskit をローカルで構成](configure-qiskit-local)します。
|
|
||||||
- [Hello world](hello-world) の手順に従って、量子プログラムを作成して実行します。
|
|
||||||
- [クラウドで IBM Quantum の使用を開始](https://cloud.ibm.com/docs/quantum-computing?topic=quantum-computing-get-started)します。
|
|
||||||
- [ワークフローのサンプルチュートリアル](https://learning.quantum.ibm.com/catalog/tutorials?category=workflow-example)の 1 つを試します。
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
````
|
|
|
@ -1,104 +0,0 @@
|
||||||
---
|
|
||||||
title: Getting help
|
|
||||||
description: How to find answers to questions or problems you encounter while using IBM Quantum (Platform, or on IBM Cloud) or Qiskit Runtime
|
|
||||||
---
|
|
||||||
|
|
||||||
# Getting help
|
|
||||||
|
|
||||||
## IBM Quantum Support
|
|
||||||
|
|
||||||
Members of the IBM Quantum Network can reach out to IBM Quantum Support if they have technical difficulties, questions, or concerns. Ask your administrator or IBM representative for IBM Quantum Support contact information.
|
|
||||||
|
|
||||||
## Qiskit
|
|
||||||
|
|
||||||
For help with Qiskit, access our Slack community: [Qiskit Slack](https://qisk.it/join-slack).
|
|
||||||
|
|
||||||
## Qiskit Runtime
|
|
||||||
|
|
||||||
- Join the qiskit-runtime channel within the [Qiskit Slack workspace](https://qisk.it/join-slack).
|
|
||||||
|
|
||||||
## Open-source governance
|
|
||||||
|
|
||||||
The following pages are resources for anyone interested in contributing code to Qiskit.
|
|
||||||
|
|
||||||
- [Code of conduct](https://github.com/Qiskit/qiskit/blob/main/CODE_OF_CONDUCT.md)
|
|
||||||
- [Contributing guide](https://github.com/Qiskit/qiskit/blob/main/CONTRIBUTING.md)
|
|
||||||
- [Deprecation policy](https://github.com/Qiskit/qiskit/blob/main/DEPRECATION.md)
|
|
||||||
- [Maintainers guide](https://github.com/Qiskit/qiskit/blob/main/MAINTAINING.md)
|
|
||||||
|
|
||||||
## Other discussions
|
|
||||||
|
|
||||||
Discuss quantum information science and development with the larger quantum computing field on the [Quantum Computing Stack Exchange](https://quantumcomputing.stackexchange.com/questions/) site. Be sure to read the ["How do I ask a good question?"](https://quantumcomputing.stackexchange.com/help/how-to-ask) guide, and make use of tags such as `qiskit`, `ibm-runtime`, and `ibm-quantum-services` for best results.
|
|
||||||
|
|
||||||
For questions specific to programming, visit [Stack Overflow](https://stackoverflow.com/) and use the tag `qiskit`.
|
|
||||||
|
|
||||||
## Frequently asked questions
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
How do I cite Qiskit in my research?
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
Cite Qiskit by using the included [BibTeX file](https://github.com/Qiskit/qiskit/blob/main/CITATION.bib).
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
How do I cite an IBM Quantum system in my research?
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
For research papers, we encourage authors to acknowledge IBM Quantum using:
|
|
||||||
|
|
||||||
> We acknowledge the use of IBM Quantum services for this work. The views expressed are those of the authors, and do not reflect the official policy or position of IBM or the IBM Quantum team.
|
|
||||||
|
|
||||||
Paper references should be cited as follows:
|
|
||||||
|
|
||||||
> IBM Quantum. https://<span>quantum.ibm.com</span>/, 2021
|
|
||||||
|
|
||||||
Systems in the paper should be referenced by their unique name (i.e., `ibmq_vigo`) and optionally
|
|
||||||
adding the version (i.e., `ibmq_vigo` v1.0.2). We also encourage referencing the processor.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
> In this paper we used `ibmq_vigo`, which is one of the IBM Quantum Canary processors.
|
|
||||||
|
|
||||||
An example of citing an IBM Quantum program:
|
|
||||||
|
|
||||||
> IBM Quantum (2022). Estimator primitive (Version x.y.z) [computer software]. https://<span>quantum.ibm.com</span>/
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
How do I cite IBM Quantum Composer in my research?
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
An example of citing IBM Quantum Composer:
|
|
||||||
|
|
||||||
> IBM Quantum Composer. 2023. url: https://<span>quantum.ibm.com/composer</span>
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
Why do I receive the error message `AttributeError: QuantumCircuit object has no attribute 'save_state'` when using `save_*`method on a circuit?
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
The `save_*` instructions are part of Qiskit Aer project,
|
|
||||||
a high performance simulator for quantum circuits. These instructions do not
|
|
||||||
exist outside of Qiskit Aer and are added dynamically to the
|
|
||||||
[QuantumCircuit](/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit) class by Qiskit Aer on import. If you would like to
|
|
||||||
use these instructions you must first ensure that you have imported
|
|
||||||
`qiskit_aer` in your program before trying to call these methods. You
|
|
||||||
can refer to [qiskit_aer.library](https://qiskit.org/ecosystem/aer/apidocs/aer_library.html) for the details of these custom
|
|
||||||
instructions included with Qiskit Aer.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
Why do my results from real devices differ from my results from the simulator?
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
The simulator models an ideal environment, without noise or decoherence. When jobs are run on the real devices, noise from the environment and decoherence cause the qubits to behave differently than in an ideal environment.
|
|
||||||
|
|
||||||
</details>
|
|
|
@ -1,60 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Transpile",
|
|
||||||
"collapsed": true,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Introduction",
|
|
||||||
"url": "/transpile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Transpiler stages",
|
|
||||||
"url": "/transpile/transpiler-stages"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Transpile with pass managers",
|
|
||||||
"url": "/transpile/transpile-with-pass-managers"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Create a pass manager for dynamical decoupling",
|
|
||||||
"url": "/transpile/dynamical-decoupling-pass-manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Write a custom transpiler pass",
|
|
||||||
"url": "/transpile/custom-transpiler-pass"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Use the transpile function",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Default settings and configuration options",
|
|
||||||
"url": "/transpile/defaults-and-configuration-options"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Set optimization level",
|
|
||||||
"url": "/transpile/set-optimization"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Represent quantum computers",
|
|
||||||
"url": "/transpile/representing_quantum_computers"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Commonly used parameters for transpilation",
|
|
||||||
"url": "/transpile/common-parameters"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Qiskit transpiler service",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Transpile circuits remotely with the Qiskit transpiler service",
|
|
||||||
"url": "/transpile/qiskit-transpiler-service"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "AI transpiler passes",
|
|
||||||
"url": "/transpile/ai-transpiler-passes"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
---
|
|
||||||
title: AI transpiler passes
|
|
||||||
description: What are the AI transpiler passes and how to use them
|
|
||||||
---
|
|
||||||
|
|
||||||
# AI transpiler passes
|
|
||||||
|
|
||||||
|
|
||||||
The AI-powered transpiler passes are experimental passes that work as a drop-in replacement of "traditional" qiskit passes for some transpiling tasks. They often produce better results than existing heuristic algorithms (such as lower depth and CNOT count), but are also much faster than optimization algorithms such as Boolean satisfiability solvers. The AI transpiler passes run on the cloud and are available to IBM Quantum Premium Plan users.
|
|
||||||
|
|
||||||
<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.
|
|
||||||
</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
|
|
||||||
- `AIPermutationSynthesis`: Permutation circuit synthesis
|
|
||||||
|
|
||||||
To use the AI transpiler passes through our cloud services, install the `qiskit-transpiler-service` package (see instructions [here](qiskit-transpiler-service#install-transpiler-service)).
|
|
||||||
|
|
||||||
## AI routing pass
|
|
||||||
|
|
||||||
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_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")
|
|
||||||
])
|
|
||||||
|
|
||||||
circuit = EfficientSU2(120, 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.
|
|
||||||
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>
|
|
|
@ -1,113 +0,0 @@
|
||||||
---
|
|
||||||
title: Commonly used parameters for transpilation
|
|
||||||
description: Commonly used parameters such as approximation degree
|
|
||||||
---
|
|
||||||
|
|
||||||
# Commonly used parameters for transpilation
|
|
||||||
|
|
||||||
Following are some of the more commonly used parameters for local transpilation using the `transpile()` method.
|
|
||||||
|
|
||||||
<span id="approx-degree"></span>
|
|
||||||
## Approximation degree
|
|
||||||
|
|
||||||
You can use the approximation degree to specify how closely you want the resultant circuit to match the desired (input) circuit. This is a float in the range (0.0 - 1.0), where 0.0 is maximum approximation and 1.0 (default) is no approximation. Smaller values trade output accuracy for ease of execution (that is, fewer gates). The default value is 1.0.
|
|
||||||
|
|
||||||
In two-qubit unitary synthesis (used in initial stages of all levels and for optimization stage with optimization level 3), this value specifies the target fidelity of the output decomposition. That is, how much error is introduced when a matrix representation of a circuit is converted to discrete gates. If the approximation degree is a lower value (more approximation), the output circuit from synthesis will differ more from the input matrix, but will also likely have fewer gates (because any arbitrary two-qubit operation can be decomposed perfectly with at most three CX gates) and is easier to run.
|
|
||||||
|
|
||||||
When the approximation degree is less than 1.0, circuits with one or two CX gates might be synthesized, leading to less error from the hardware, but more from the approximation. Since CX is the most expensive gate in terms of error, it might be beneficial to decrease the number of them at the cost of fidelity in synthesis (this technique was used to increase quantum volume on IBM devices: [Validating quantum computers using randomized model circuits](https://arxiv.org/abs/1811.12926)).
|
|
||||||
|
|
||||||
As an example, we generate a random 2-qubit `UnitaryGate` which will be synthesized in the initial stage. Setting the `approximation_degree` less than 1.0 might generate an approximate circuit. We must also specify the `basis_gates` to let the synthesis method know which gates it can use for the approximate synthesis.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit, transpile
|
|
||||||
from qiskit.circuit.library import UnitaryGate
|
|
||||||
from qiskit.quantum_info import random_unitary
|
|
||||||
|
|
||||||
UU = random_unitary(4, seed=12345)
|
|
||||||
rand_U = UnitaryGate(UU)
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.append(rand_U, range(2))
|
|
||||||
approx_qc = transpile(qc, approximation_degree=0.85, basis_gates=["sx", "rz", "cx"])
|
|
||||||
print(approx_qc.count_ops()["cx"])
|
|
||||||
```
|
|
||||||
|
|
||||||
This yields an output of `2` because the approximation requires fewer CX gates.
|
|
||||||
|
|
||||||
<span id="seed"></span>
|
|
||||||
## Seed transpiler
|
|
||||||
|
|
||||||
The seed transpiler argument sets the random seed for the stochastic parts of the transpiler, used for reproducibility. Due to the stochastic nature of the transpiler if you run `transpile()` multiple times with the same configuration you are not guaranteed to get the same output each time. So if you are experimenting with transpilation and require the same transpiled output every time you can do so by setting the `seed_transpiler` argument.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
optimized_1 = transpile(qc, seed_transpiler=11, optimization_level=1)
|
|
||||||
```
|
|
||||||
|
|
||||||
<span id="init-layout"></span>
|
|
||||||
## Initial layout
|
|
||||||
|
|
||||||
Specifies the initial position of virtual qubits on physical qubits. If this layout makes the circuit compatible with the `coupling_map` constraints, it will be used. The final layout is not guaranteed to be the same, as the transpiler might permute qubits through swaps or other means. Multiple formats are supported:
|
|
||||||
|
|
||||||
````
|
|
||||||
* Layout instance
|
|
||||||
* Dict
|
|
||||||
- virtual to physical:
|
|
||||||
```python
|
|
||||||
{qr[0]: 0,
|
|
||||||
qr[1]: 3,
|
|
||||||
qr[2]: 5}
|
|
||||||
```
|
|
||||||
- physical to virtual:
|
|
||||||
```python
|
|
||||||
{0: qr[0],
|
|
||||||
3: qr[1],
|
|
||||||
5: qr[2]}
|
|
||||||
```
|
|
||||||
|
|
||||||
* List
|
|
||||||
- virtual to physical:
|
|
||||||
```python
|
|
||||||
[0, 3, 5] # virtual qubits are ordered (in addition to named)
|
|
||||||
```
|
|
||||||
- physical to virtual:
|
|
||||||
```python
|
|
||||||
[qr[0], None, None, qr[1], None, qr[2]]
|
|
||||||
```
|
|
||||||
````
|
|
||||||
|
|
||||||
<span id="xx-method"></span>
|
|
||||||
## *_method
|
|
||||||
|
|
||||||
These options influence how the transpiler works and are used to try and get better, different, or specific output from the transpiler.
|
|
||||||
|
|
||||||
- `init_method` (str) - The plugin to use for the initialization stage.
|
|
||||||
|
|
||||||
- `layout_method` (str) - The layout selection pass (`trivial`, `dense`, `noise_adaptive`, `sabre`). This can also be the external plugin name to use for the layout stage.
|
|
||||||
|
|
||||||
- `optimization_method` (str) - The plugin to use for the optimization stage.
|
|
||||||
|
|
||||||
- `routing_method` (str) - Name of routing pass (`basic`, `lookahead`, `stochastic`, `sabre`, `none`). This can also be the external plugin name to use for the routing stage.
|
|
||||||
|
|
||||||
- `scheduling_method` (str) - Name of scheduling pass. This can also be the external plugin name to use for the scheduling stage.
|
|
||||||
- `as_soon_as_possible`: Schedule instructions greedily: as early as possible on a qubit resource (alias: `asap`).
|
|
||||||
- `as_late_as_possible`: Schedule instructions late. That is, keep qubits in the ground state when possible (alias: `alap`).
|
|
||||||
|
|
||||||
- `translation_method` (str) - Name of translation pass (`unroller`, `translator`, `synthesis`). This can also be the external plugin name to use for the translation stage.
|
|
||||||
|
|
||||||
- `unitary_synthesis_method` (str) - The name of the unitary synthesis method to use. By default `default` is used.
|
|
||||||
|
|
||||||
<Admonition>
|
|
||||||
To see a list of all installed plugins for a given stage you can run [`list_stage_plugins("stage_name")`](https://docs.quantum.ibm.com/api/qiskit/transpiler_plugins#plugin-api). For example if you want to see a list of all installed plugins for the routing stage run `list_stage_plugins(routing)`.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendation">
|
|
||||||
- Review the [Default options and configuration settings](defaults-and-configuration-options) topic.
|
|
||||||
- Learn how to [Set the optimization level.](set-optimization)
|
|
||||||
- Try the [Submit transpiled circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) tutorial.
|
|
||||||
- Review the [Transpile API documentation.](/api/qiskit/transpiler)
|
|
||||||
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
|
@ -1,217 +0,0 @@
|
||||||
---
|
|
||||||
title: Transpilation defaults and configuration options
|
|
||||||
description: Default settings and configuration options
|
|
||||||
---
|
|
||||||
|
|
||||||
# Transpilation default settings and configuration options
|
|
||||||
|
|
||||||
Abstract circuits need to be transpiled because systems have a limited set of basis gates and cannot execute arbitrary operations. The transpiler's function is to change arbitrary circuits so that they can run on a specified system. This is done by translating the circuits to the supported basis gates, and by introducing SWAP gates as needed, so that the circuit's connectivity matches that of the system.
|
|
||||||
|
|
||||||
You can pass circuits and a system to the `transpile()` function and use all default settings, or you can use parameters to fine tune the transpilation.
|
|
||||||
|
|
||||||
## Basic usage without parameters
|
|
||||||
|
|
||||||
In this example, we pass a circuit and target system to the transpiler without specifying any further parameters.
|
|
||||||
|
|
||||||
Create a circuit and view the result:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import transpile
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
from qiskit.circuit.library import GroverOperator, Diagonal
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
from qiskit.providers.fake_provider import FakeSherbrooke
|
|
||||||
|
|
||||||
# Create circuit to test transpiler on
|
|
||||||
oracle = Diagonal([1] * 7 + [-1])
|
|
||||||
qc = QuantumCircuit(3)
|
|
||||||
qc.h([0, 1, 2])
|
|
||||||
qc = qc.compose(GroverOperator(oracle))
|
|
||||||
|
|
||||||
# Add measurements to the circuit
|
|
||||||
qc.measure_all()
|
|
||||||
|
|
||||||
# View the circuit
|
|
||||||
qc.draw(output='mpl')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Original circuit](/images/transpile/defaults-and-configuration-options/original-circuit.png "Original circuit")
|
|
||||||
|
|
||||||
Transpile the circuit and view the result:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Specify the system to target
|
|
||||||
backend = FakeSherbrooke()
|
|
||||||
|
|
||||||
# Transpile the circuit
|
|
||||||
transpiled_circ = transpile(qc, backend)
|
|
||||||
|
|
||||||
# View the transpiled circuit
|
|
||||||
transpiled_circ.draw(output='mpl')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Transpiled circuit](/images/transpile/defaults-and-configuration-options/transpiled-circuit.png "Transpiled circuit")
|
|
||||||
|
|
||||||
## All available parameters
|
|
||||||
|
|
||||||
Following are all of the available parameters for the `transpile()` method. There are two classes of arguments: those that describe the target of compilation, and those that influence how the transpiler works.
|
|
||||||
|
|
||||||
All parameters except `circuits` are optional. For full details, see the [Transpiler API documentation](/api/qiskit/transpiler#transpiler-api).
|
|
||||||
|
|
||||||
`circuits` (`_CircuitT`) - One or more circuits to transpile. This is the only required parameter.
|
|
||||||
|
|
||||||
### Parameters used to describe the compilation target:
|
|
||||||
|
|
||||||
These arguments describe the system that the input circuit will be run on. For example, they may be used to ensure that the returned circuit can be run on the specified system, where the transpiler maps the circuit's virtual qubits to the physical qubits which may have limited connectivity as specified in the `coupling_map`, `basis_gates` that specify which single- and two-qubit gates are calibrated for the system, and possibly their error rates.
|
|
||||||
|
|
||||||
Many of these parameters are described in detail in [Commonly used parameters for transpilation](common-parameters).
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**System (`Backend`) parameters**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
**Backend parameters** - If you specify `backend`, you don't need to specify `target` or any other backend options. Likewise, if you specify `target`, you don't need to specify `backend` or any other backend options.
|
|
||||||
|
|
||||||
- `backend` (Backend) - If this is set, the transpiler compiles the input circuit to this device. If any other option is set that impacts these settings, such as `coupling_map`, it overrides the settings from `backend`.
|
|
||||||
- `target` (Target) - A backend transpiler target. Normally this is specified as part of the backend argument, but if you manually constructed a Target object, you can specify it here. This overrides the target from `backend`.
|
|
||||||
- `backend_properties` (BackendProperties) - Properties returned by a system, including information on gate errors, readout errors, qubit coherence times, and so on. Find a system that provides this information by running `backend.properties()`.
|
|
||||||
- `dt` (float | None) - Backend sample time (resolution) in seconds. If `None` is specified (default), `backend.configuration().dt` is used.
|
|
||||||
- `ignore_backend_supplied_default_methods` (bool) - If set to `True`, any default methods specified by a system are ignored. Some systems specify alternative default methods to support custom compilation target-specific passes / plugins that support system-specific compilation techniques. If you prefer that these defaults are not used, this option disables those system-specific defaults.
|
|
||||||
- `instruction_durations` (List\[Tuple\[str, Iterable[int], float, Iterable[float], str]] | List\[Tuple\[str, Iterable[int], float, Iterable[float]]] | List\[Tuple\[str, Iterable[int], float, str]] | List\[Tuple\[str, Iterable[int], float]] | InstructionDurations) - Durations of instructions. Applicable only if `scheduling_method` is specified. The gate lengths defined in `backend.properties` are used by default. They are overwritten if `instruction_durations` is specified. The `instruction_durations` format must be as follows. The instruction_durations must be given as a list of tuples [(instruction_name, qubits, duration, unit), …]. | \[(`cx`, [0, 1], 12.3, `ns`), (`u3`, [0], 4.56, `ns`)] | \[(`cx`, [0, 1], 1000), (`u3`, [0], 300)] If `unit` is omitted, the default is `dt`, which is a sample time depending on system. If the time unit is `dt`, the duration must be an integer.
|
|
||||||
- `timing_constraints` (Dict[str, int] | None) - An optional control hardware restriction on instruction time resolution. This information is provided by the system configuration. If the system doesn’t have any restriction on the instruction time allocation, `timing_constraints` is `None` and no adjustment is performed. A system might report a set of restrictions, namely:
|
|
||||||
\- `granularity`: An integer value representing the minimum pulse gate resolution in units of dt. A user-defined pulse gate should have duration that is a multiple of this granularity value.
|
|
||||||
\- `min_length`: An integer value representing the minimum pulse gate length in units of dt. A user-defined pulse gate should be longer than this length.
|
|
||||||
\- `pulse_alignment`: An integer value representing a time resolution of gate instruction starting time. Gate instructions should start at time that is a multiple of this value.
|
|
||||||
\- `acquire_alignment`: An integer value representing a time resolution of measure instruction starting time. Measure instruction should start at time that is a multiple of this value.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Layout and topology parameters**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `basis_gates` (List[str] | None) - List of basis gate names to unroll to. For example ['u1', 'u2', 'u3', 'cx']. If `None`, do not unroll.
|
|
||||||
- `coupling_map` (CouplingMap | List\[List[int]]) - Directed coupling map (possibly custom) to target in mapping. If the coupling map is symmetric, both directions need to be specified. These formats are supported:
|
|
||||||
- CouplingMap instance
|
|
||||||
- List, must be given as an adjacency matrix, where each entry specifies all directed two-qubit interactions supported by the system. For example:\[[0, 1], [0, 3], [1, 2], [1, 5], [2, 5], [4, 1], [5, 3]]
|
|
||||||
- `inst_map` (List[InstructionScheduleMap] | None) - Mapping of circuit operations to pulse schedules. If `None`, the system’s `instruction_schedule_map` is used.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### Parameters used to influence how the transpiler works:
|
|
||||||
|
|
||||||
These parameters impact specific transpilation stages. Some of them might impact multiple stages, but have only been listed under one stage for simplicity. If you specify an argument, such as `initial_layout` for the qubits you want to use, that value overrides all the passes that could change it. In other words, the transpiler won't change anything that you manually specify. For details about specific stages, see [Transpiler stages](transpiler-stages).
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Initialization stage**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `hls_config` (HLSConfig) - An optional configuration class `HLSConfig` that is passed directly to the `HighLevelSynthesis` transformation pass. This configuration class lets you specify the lists of synthesis algorithms and their parameters for various high-level objects.
|
|
||||||
- `init_method` (str) - The plugin name to use for the initialization stage. By default, an external plugin is not used. You can see a list of installed plugins by running `list_stage_plugins()` with `init` for the stage name argument.
|
|
||||||
- `unitary_synthesis_method` (str) - The name of the unitary synthesis method to use. By default, `default` is used. You can see a list of installed plugins by running `unitary_synthesis_plugin_names()`.
|
|
||||||
- `unitary_synthesis_plugin_config` (dict) - An optional configuration dictionary that is passed directly to the unitary synthesis plugin. By default this setting has no effect because the default unitary synthesis method does not take custom configuration. Applying a custom configuration should only be necessary when a unitary synthesis plugin is specified with the `unitary_synthesis` argument. As this is custom for each unitary synthesis plugin, refer to the plugin's documentation for how to use this option.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Translation stage**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `translation_method` (str) - Name of translation pass (`basis_translator`, `translator`, or `synthesis`) This can also be the external plugin name to use for the translation stage. You can see a list of installed plugins by running `list_stage_plugins()` with `translation` for the `stage_name` argument. The default value is `basis_translator`.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Layout stage**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `initial_layout` (Layout | Dict | List) - Initial position of virtual qubits on physical qubits. If this layout makes the circuit compatible with the `coupling_map` constraints, it will be used. The final layout is not guaranteed to be the same, as the transpiler might permute qubits through swaps or other means. For full details, see the [Initial layout section.](common-parameters#initial-layout)
|
|
||||||
- `layout_method` (str) - Name of layout selection pass (`trivial`, `dense`, `noise_adaptive`, or `sabre`). This can also be the external plugin name to use for the layout stage. You can see a list of installed plugins by running `list_stage_plugins()` with `layout` for the `stage_name` argument. The default value is `sabre`.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Routing stage**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `routing_method` (str) - Name of routing pass (`basic`, `lookahead`, `stochastic`, `sabre`, or `none`). This can also be the external plugin name to use for the routing stage. You can see a list of installed plugins by running `list_stage_plugins()` with `routing` for the `stage_name` argument. The default value is `sabre`.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Optimization stage**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `approximation_degree` (float, in the range 0-1 | None) - Heuristic dial used for circuit approximation (1.0 = no approximation, 0.0 = maximal approximation). The default value is 1.0. Specifying `None` sets the approximation degree to the reported error rate. See the [Approximation degree section](common-parameters#approx-degree) for more details.
|
|
||||||
- `optimization_level` (int) - How much optimization to perform on the circuits. Integer in the range (0 - 3). Higher levels generate more optimized circuits, at the expense of longer transpilation time. The default is `1`. See the [Set optimization topic](set-optimization) for more details.
|
|
||||||
- `optimization_method` (str) - The plugin name to use for the optimization stage. By default an external plugin is not used. You can see a list of installed plugins by running `list_stage_plugins()` with `optimization` for the `stage_name` argument.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Scheduling stage**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
- `scheduling_method` (str) - Name of the scheduling pass. This can also be the external plugin name to use for the scheduling stage. You can see a list of installed plugins by running `list_stage_plugins()` with `scheduling` for the `stage_name` argument.
|
|
||||||
- 'as_soon_as_possible': Schedule instructions greedily, as early as possible on a qubit resource. (alias: `asap`)
|
|
||||||
- 'as_late_as_possible': Schedule instructions late, that is, keeping qubits in the ground state when possible. (alias: `alap`). This is the default.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
**Transpiler execution**
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
`callback` (Callable\[[BasePass, DAGCircuit, float, PropertySet, int], Any]) - A callback function is one that is called after each pass execution. This is useful for debugging. Since the transpiler substantially transforms a circuit, the callback mechanism helps you understand what the transpiler is doing after each pass. For example, if you see an unexpected circuit, you can write a callback to draw the circuit and print the pass name after each pass.
|
|
||||||
|
|
||||||
The function is called with these keyword arguments:
|
|
||||||
|
|
||||||
- `pass_`: the pass being run.
|
|
||||||
- `dag`: the dag output of the pass.
|
|
||||||
- `time`: the time to execute the pass.
|
|
||||||
- `property_set`: the property set.
|
|
||||||
- `count`: the index for the pass execution.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The arguments passed expose the internals of the pass manager and are subject to change as the pass manager internals change. If you intend to reuse a callback function over multiple releases, verify that the arguments being passed are the same.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
To use the callback feature, define a function that will take in kwargs dict and access the variables. For example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def callback_func(**kwargs):
|
|
||||||
pass_ = kwargs['pass_']
|
|
||||||
dag = kwargs['dag']
|
|
||||||
time = kwargs['time']
|
|
||||||
property_set = kwargs['property_set']
|
|
||||||
count = kwargs['count']
|
|
||||||
...
|
|
||||||
transpile(circ, callback=callback_func)
|
|
||||||
```
|
|
||||||
|
|
||||||
- `seed_transpiler` (int) - Sets random seeds for the stochastic parts of the transpiler.
|
|
||||||
- `output_name` (str | List[str]) - A list with strings to identify the output circuits. The length of the list should be the same length as the circuits parameter.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<Admonition>
|
|
||||||
The following default values are used if you don't specify any of the above parameters.
|
|
||||||
|
|
||||||
```python
|
|
||||||
qiskit.compiler.transpile(unitary_synthesis_method='default', translation_method='basis_translator', layout_method='sabre', routing_method='sabre', approximation_degree=1.0, optimization_level=1.0, scheduling_method='as_late_as_possible')
|
|
||||||
```
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Learn how to [Set the optimization level](set-optimization).
|
|
||||||
- Review more [Commonly used parameters](common-parameters).
|
|
||||||
- Learn how to [Set the optimization level when using Qiskit Runtime.](../run/advanced-runtime-options)
|
|
||||||
- Visit the [Transpile with pass managers](transpile-with-pass-managers) topic.
|
|
||||||
- For examples, see [Representing quantum computers.](representing_quantum_computers)
|
|
||||||
- Try the [Submit transpiled circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) tutorial.
|
|
||||||
- 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 [Transpile API documentation](/api/qiskit/transpiler).
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
|
@ -1,52 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduction
|
|
||||||
description: Introduction to the transpiler
|
|
||||||
---
|
|
||||||
|
|
||||||
# Introduction
|
|
||||||
|
|
||||||
Transpilation is the process of rewriting a given input circuit to match the topology of a specific quantum device, and optimize the circuit instructions for execution on noisy quantum systems. This documentation covers the tooling and workflows for local transpilation available to all Qiskit users, as well as for the cloud-based [Qiskit transpiler service](qiskit-transpiler-service) available to Premium Plan users. If you're using primitives and are only interested in the default transpilation options provided by the Qiskit Runtime service, read the [Configure runtime compilation for Qiskit Runtime](../run/configure-runtime-compilation) topic.
|
|
||||||
|
|
||||||
A central component of Qiskit, the transpiler is designed for modularity and extensibility. Its central goal is to write new circuit transformations (known as transpiler **passes**), and combine them with other existing passes, greatly reducing the depth and complexity of quantum circuits. Which passes are chained together and in which order has a major effect on the final outcome. This pipeline is determined by the [`PassManager`](/api/qiskit/qiskit.transpiler.PassManager) and [`StagedPassManager`](/api/qiskit/qiskit.transpiler.StagedPassManager) objects. The `StagedPassManager` orchestrates the execution of one or more `PassManagers` and determines the order in which they are executed, while the `PassManager` object is merely a collection of one or more passes. Think of the `StagedPassManager` as the conductor in an orchestra, the `PassManagers` as the different instrument sections, and the `Pass`es as the individual musicians. In this way, you can compose hardware-efficient quantum circuits that let you execute utility-scale work while keeping noise manageable.
|
|
||||||
|
|
||||||
Find more information about the pass manager stages in the [Transpiler stages](transpiler-stages) topic.
|
|
||||||
|
|
||||||
<Admonition type="caution">
|
|
||||||
If you perform transpilation locally and submit the transpiled circuits to the Qiskit Runtime service, set the `skip_transpilation` option to `True` so that the service does not try to apply further transformations to your circuit. See [Advanced runtime compilation options](/run/configure-runtime-compilation#advanced-runtime-compilation-options).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Transpiler stages
|
|
||||||
|
|
||||||
Qiskit's prebuilt transpiler pipeline consists of six fundamental stages:
|
|
||||||
|
|
||||||
1. `init` - This pass runs any initial passes that are required before we start embedding the circuit to the system. This typically involves unrolling custom instructions and converting the circuit to all single- and two-qubit gates. (By default this will just validate the circuit instructions and translate multi-qubit gates into single- and two-qubit gates.)
|
|
||||||
2. `layout` - This pass applies a _layout_, mapping/assigning the virtual qubits in your circuit to the physical qubits of a system.
|
|
||||||
3. `routing` - This pass runs after a layout has been applied and will inject gates (i.e., SWAPs) in the original circuit in order to make it compatible with the system's connectivity/coupling map.
|
|
||||||
4. `translation` - This pass translates the gates in the circuit to the system's basis set of instructions.
|
|
||||||
5. `optimization` - This pass runs an optimization loop to find more efficient decompositions of your quantum circuit until a condition is met (such as a fixed depth).
|
|
||||||
6. `scheduling` - This stage is for any hardware-aware scheduling passes. If the user specifies a scheduling method, this stage accounts for all idle time in the circuit.
|
|
||||||
|
|
||||||
If you decide to customize your own transpilation workflow, we suggest using these stages as a guideline during development.
|
|
||||||
|
|
||||||
## Transpile with pass managers
|
|
||||||
|
|
||||||
The recommended way to transpile a circuit is to create a staged pass manager and then execute its `run` method with your circuit as input. You can use the [`generate_preset_pass_manager`](/api/qiskit/transpiler_preset#qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager) function to generate a staged pass manager with reasonable defaults.
|
|
||||||
|
|
||||||
More advanced users can customize a set of `PassManager` and `StagedPassManager` objects and determine the order in which each stage is run. This can dramatically change the final output circuit. In fact, a custom approach to transpiling a quantum algorithm often produces more efficient error suppression than the default approach. This involves rewriting quantum circuits to match hardware constraints and suppress the effects of noise. The flow of logic for this tool chain is quite customizable and need not be linear. The transpilation process can even prepare iterative loops, conditional branches, and other complex behaviors. A good starting place when developing a set of custom passes is to examine the default sequence of transformations.
|
|
||||||
|
|
||||||
For an overview of transpiling using pass managers, see [Transpile with pass managers](transpile-with-pass-managers).
|
|
||||||
|
|
||||||
## Default transpilation
|
|
||||||
|
|
||||||
For a simpler , but less customizable, "out-of-the-box" way to use the transpiler, use the [`qiskit.compiler.transpile`](/api/qiskit/compiler#qiskit.compiler.transpile) function. This generates and runs one of the preset `StagedPassManager`s based on, among other options, an `optimization_level` flag that can be set to 0, 1, 2, or 3. Higher levels generate more optimized circuits, at the expense of longer transpilation times.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- To learn how to use the `transpile` function, start with the [Transpilation default settings and configuration options](defaults-and-configuration-options) topic.
|
|
||||||
- Continue learning about transpilation with the [Transpiler stages](transpiler-stages) topic.
|
|
||||||
- Try the [Submit transpiled circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) tutorial.
|
|
||||||
- Learn [how to transpile circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) as part of Qiskit Patterns workflows using Qiskit Runtime.
|
|
||||||
- Try an end-to-end example that uses transpiled circuits in the [Variational quantum eigensolver (VQE)](https://learning.quantum.ibm.com/tutorial/variational-quantum-eigensolver) tutorial.
|
|
||||||
- See the [Transpile API documentation.](https://docs.quantum-computing.ibm.com/api/qiskit/transpiler)
|
|
||||||
</Admonition>
|
|
|
@ -1,78 +0,0 @@
|
||||||
---
|
|
||||||
title: Transpile circuits remotely with the Qiskit transpiler service
|
|
||||||
description: What is the Qiskit transpiler service and how to use it
|
|
||||||
---
|
|
||||||
|
|
||||||
# Transpile circuits remotely with the Qiskit transpiler service
|
|
||||||
|
|
||||||
The Qiskit transpiler service provides transpilation capabilities on the cloud. In addition to the local Qiskit transpiler capabilities, your transpilation tasks can benefit from both IBM Quantum Cloud resources and AI-powered transpiler passes.
|
|
||||||
|
|
||||||
The Qiskit transpiler service offers a Python library to seamlessly integrate this service and its capabilities into your current Qiskit patterns and workflows.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
This experimental service is only available for IBM Quantum Premium Plan users.
|
|
||||||
The service is an alpha release, subject to change.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="install-transpiler-service"></span>
|
|
||||||
## Install the qiskit-transpiler-service package
|
|
||||||
|
|
||||||
To use the Qiskit transpiler service, install the `qiskit-transpiler-service` package:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
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`).
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
- `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.
|
|
||||||
- `qiskit_transpile_options` (dict) - A Python dictionary object that can include any other option that is valid in the [Qiskit `transpile()` method](defaults-and-configuration-options). If the `qiskit_transpile_options` input includes `optimization_level`, it is discarded in favor of the `optimization_level` specified as parameter input. If the `qiskit_transpile_options` includes any option not recognized by the Qiskit `transpile()` method, the library raises an error.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit.random import random_circuit
|
|
||||||
from qiskit_transpiler_service.transpiler_service import TranspilerService
|
|
||||||
|
|
||||||
random_circ = random_circuit(5, depth=3, seed=42).decompose(reps=3)
|
|
||||||
|
|
||||||
cloud_transpiler_service = TranspilerService(
|
|
||||||
target="ibm_cairo",
|
|
||||||
ai=False,
|
|
||||||
optimization_level=1,
|
|
||||||
)
|
|
||||||
transpiled_circuit = cloud_transpiler_service.run(random_circ)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Produce a similar random 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_transpiler_service.transpiler_service import TranspilerService
|
|
||||||
|
|
||||||
random_circ = random_circuit(5, depth=3, seed=42).decompose(reps=3)
|
|
||||||
|
|
||||||
cloud_transpiler_service = TranspilerService(
|
|
||||||
target="ibm_cairo",
|
|
||||||
ai=True,
|
|
||||||
optimization_level=1,
|
|
||||||
)
|
|
||||||
transpiled_circuit = cloud_transpiler_service.run(random_circ)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Learn how to create [AI transpiler passes.](ai-transpiler-passes)
|
|
||||||
- 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>
|
|
|
@ -1,177 +0,0 @@
|
||||||
---
|
|
||||||
title: Representing quantum computers
|
|
||||||
description: Learn about coupling maps, basis gates and system errors for transpiling
|
|
||||||
---
|
|
||||||
|
|
||||||
# Represent quantum computers
|
|
||||||
|
|
||||||
To construct an equivalent circuit that can run on a specific system, the transpiler needs certain details about the system. Typically, this information is found in the `backend` or `target = backend.target` class, so you don't need to pass anything further to the transpiler. However, if more infomation is provided, the transpiler can use it to try to produce the best circuit to run on that hardware.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Because many of the underlying transpilation algorithms are stochastic, there is no guarantee that a better circuit will be found.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
<span id="default-config"></span>
|
|
||||||
## Default configuration
|
|
||||||
|
|
||||||
The simplest use of the transpiler is to provide all the system information by providing the `backend` or `target`. To better understand how the transpiler works, construct a circuit and transpile it with different information:
|
|
||||||
|
|
||||||
Import the necessary libraries and instantiate the system or simulator:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import transpile
|
|
||||||
from qiskit.circuit.library import EfficientSU2
|
|
||||||
from qiskit.providers.fake_provider import FakeSherbrooke
|
|
||||||
|
|
||||||
backend = FakeSherbrooke()
|
|
||||||
target = backend.target
|
|
||||||
```
|
|
||||||
|
|
||||||
The `EfficientSU2` circuit consists of layers of single qubit operations spanned by `SU(2)` and `CX` entanglements. This is a heuristic pattern that can be used to prepare trial wave functions for variational quantum algorithms or classification circuits for machine learning.
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc = EfficientSU2(12, entanglement='circular', reps=1)
|
|
||||||
qc.decompose(reps=1).draw('mpl', style='iqp')
|
|
||||||
```
|
|
||||||
|
|
||||||
![The 12-qubit test circuit](/images/transpile/representing_quantum_computers/qc-circular.png "Test circuit")
|
|
||||||
|
|
||||||
### Transpile the circuit to `backend` target
|
|
||||||
|
|
||||||
This example uses the default `optimization_level=1` to transpile to the `backend` `target`, which providers all the information to the transpiler that is necessary to convert circuit to one that will run on the system.
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t_target = transpile(qc, target=target, seed_transpiler=12345)
|
|
||||||
qc_t_target.draw('mpl', style='iqp', idle_wires=False)
|
|
||||||
```
|
|
||||||
|
|
||||||
![The transpiled 12-qubit ansatz using Target information](/images/transpile/representing_quantum_computers/qc_t_target.png "Circuit transpiled with optimization level 1")
|
|
||||||
|
|
||||||
This example is used in later sections of this topic to illustrate that the coupling map and basis gates are the essential pieces of information to pass to the transpiler for optimal circuit construction. The system can usually select default settings for other information that is not passed in, such as timing and scheduling.
|
|
||||||
|
|
||||||
Providing the `backend` properties, including the gates' error rates, allows the transpiler to select the best set of qubits on the system.
|
|
||||||
|
|
||||||
## Coupling map
|
|
||||||
|
|
||||||
The coupling map is a graph that shows which qubits are connected and hence have 2-qubit gates between them. Sometimes this graph is directional, meaning that the 2-qubit gates can only go in one direction. However, the transpiler can always flip a gate's direction by adding additional 1-qubit gates. An abstract quantum circuit can always be represented on this graph, even if its connectivity is limited, by introducting SWAP gates to move the quantum information around.
|
|
||||||
|
|
||||||
The qubits from our abstract circuits are called _virtual qubits_ and those on the coupling map are _physical qubits_. The transpiler provides a mapping between virtual and physical qubits. One of the first steps in transpilation, the _routing_ stage, performs this mapping.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
Although the routing stage is intertwined with the _layout_ stage, which selects the actual qubits, we will consider them as separate stages for simplicity. The combination of routing and layout is called _qubit mapping_. Learn more about these stages in the [Transpiler stages](transpiler-stages) topic.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
Pass the `coupling_map` keyword argument to see its effect on the transpiler:
|
|
||||||
|
|
||||||
```python
|
|
||||||
coupling_map = target.build_coupling_map()
|
|
||||||
|
|
||||||
qc_t_cm_lv0 = transpile(qc, coupling_map=coupling_map, optimization_level=0, seed_transpiler=11)
|
|
||||||
qc_t_cm_lv0.draw('mpl', style='iqp', idle_wires=False)
|
|
||||||
```
|
|
||||||
|
|
||||||
![Ansatz transpiled to coupling map with optimization level 0](/images/transpile/representing_quantum_computers/qc_t_cm_lv0.png "Circuit transpiled with a coupling map")
|
|
||||||
|
|
||||||
As shown above, several SWAP gates were inserted (each consisting of three CX gates), which will cause a lot of errors on current devices. To see which qubits are selected on the actual qubit topology, use `plot_circuit_layout` from Qiskit Visualizations:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.visualization import plot_circuit_layout
|
|
||||||
|
|
||||||
plot_circuit_layout(qc_t_cm_lv0, backend, view='physical')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Circuit Layout for optimization level 0](/images/transpile/representing_quantum_computers/circ_layout_lv0.png "Circuit layout for optimization level 0")
|
|
||||||
|
|
||||||
This shows that our virtual qubits 0-11 were trivially mapped to the line of physical qubits 0-11. Let's return to the default (`optimization_level=1`), which uses `VF2Layout` if any routing is required.
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t_cm_lv1 = transpile(qc, coupling_map=coupling_map, seed_transpiler=11)
|
|
||||||
qc_t_cm_lv1.draw('mpl', style='iqp', idle_wires=False)
|
|
||||||
```
|
|
||||||
|
|
||||||
![Ansatz transpiled to coupling map with optimization level 1](/images/transpile/representing_quantum_computers/qc_t_cm_lv1.png "Ansatz transpiled to coupling map with optimization level 1")
|
|
||||||
|
|
||||||
Now there are no SWAP gates inserted and the physical qubits selected are the same when using the `target` class.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.visualization import plot_circuit_layout
|
|
||||||
|
|
||||||
plot_circuit_layout(qc_t_cm_lv1, backend, view='physical')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Circuit Layout for default optimization level](/images/transpile/representing_quantum_computers/circ_layout_lv1.png "Circuit Layout for default optimization level")
|
|
||||||
|
|
||||||
Now the layout is in a ring. Because this layout respects the circuit's connectivity, there are no SWAP gates, providing a much better circuit for execution.
|
|
||||||
|
|
||||||
## Basis gates
|
|
||||||
|
|
||||||
Every quantum system supports a limited instruction set, called its _basis gates_. Every gate in the circuit must be translated to the elements of this set. This set should consist of single- and two-qubit gates that provide a universal gates set, meaning that any quantum operation can be decomposed into those gates. This is done by the [BasisTranslator](../api/qiskit/qiskit.transpiler.passes.BasisTranslator), and the basis gates can be specified as a keyword argument to the transpiler to provide this information.
|
|
||||||
|
|
||||||
```python
|
|
||||||
basis_gates = list(target.operation_names)
|
|
||||||
print(basis_gates)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
['rz', 'sx', 'x', 'ecr', 'measure', 'delay']
|
|
||||||
```
|
|
||||||
|
|
||||||
The default single-qubit gates on _ibm_sherbrooke_ are `rz`, `x`, and `sx`, and the default two-qubit gate is `ecr` which stands for echoed cross resonance. CX gates are constructed from `ecr` gates, so on some systems `ecr` is specified as the two-qubit basis gate while on others `cx` is default. The `ecr` gates is the _entangling_ part of the `cx` gate. If one desires to use a gate that is not in the basis gate set, instructions for custom gates can be provided using [pulse gates](https://docs.quantum.ibm.com/api/qiskit/qiskit.transpiler.passes.PulseGates#pulsegates). In addition to the control gates, there are also `delay` and `measurement` instructions.
|
|
||||||
|
|
||||||
<Admonition>
|
|
||||||
Systems have default basis gates, but you can choose whatever gates you want, as long as you provide the instruction or add pulse gates (See [Create transpiler passes.](custom-transpiler-pass)) The default basis gates are those that calibrations have been done for on the system, so no further instruction/pulse gate needs to be provided. For example, on some systems `cx` is the default two-qubit gates and `ecr` on others.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t_cm_bg = transpile(qc, coupling_map=coupling_map, basis_gates=basis_gates, seed_transpiler=11)
|
|
||||||
qc_t_cm_bg.draw('mpl', style='iqp', fold=-1, idle_wires=False)
|
|
||||||
```
|
|
||||||
|
|
||||||
![Ansatz transpiled to coupling map and basis gates](/images/transpile/representing_quantum_computers/qc_t_cm_bg_lv1.png "Ansatz transpiled to coupling map and basis gates")
|
|
||||||
|
|
||||||
Note that the `CXGate`s have been decomposed to `ecr` gates and single-qubit basis gates.
|
|
||||||
|
|
||||||
## Including system errors
|
|
||||||
|
|
||||||
Constructing a `target` object lets you consider the qubits' error rates in addition to the `coupling_map` and `basis_gates`. The `target` object contains everything needed to target a system, but here we build one that contains a limited amount of information.
|
|
||||||
|
|
||||||
We retrieved the `target` from `backend.target` previously. This contains a lot of system information, including error rates. For example, the instruction properties of the echoed cross resonance gate between qubit 0 and 1 (not that `ecr` is directional) is retrieved by running the following command:
|
|
||||||
|
|
||||||
```python
|
|
||||||
target['ecr'][(1, 0)]
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
InstructionProperties(duration=5.333333333333332e-07, error=0.006969730734746021, calibration=PulseQobj)
|
|
||||||
```
|
|
||||||
|
|
||||||
The above result shows that the gate is 533μs with an error of 0.7%. To reveal error information to the transpiler, we will build our own target model with the `basis_gates` and `coupling_map` from above and populate it with error values from the backend `FakeSherbrooke`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.transpiler import Target
|
|
||||||
|
|
||||||
err_targ = Target.from_configuration(basis_gates=basis_gates, coupling_map=coupling_map, num_qubits=target.num_qubits)
|
|
||||||
|
|
||||||
for idx in range(len(target.instructions)):
|
|
||||||
err_targ[target.instructions[idx][0].name][target.instructions[idx][1]] = target.instruction_properties(idx)
|
|
||||||
```
|
|
||||||
|
|
||||||
Transpile with our new target `err_targ` as the target:
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t_cm_bg_et = transpile(qc, target=err_targ, seed_transpiler=11)
|
|
||||||
qc_t_cm_bg_et.draw('mpl', style='iqp', fold=-1, idle_wires=False)
|
|
||||||
```
|
|
||||||
|
|
||||||
![Ansatz transpiled to our target model](/images/transpile/representing_quantum_computers/qc_t_cm_bg_et_lv1.png "Ansatz transpiled to our target model")
|
|
||||||
|
|
||||||
Note that by including the error information, the `VF2PostLayout` pass tries to find the optimal qubits to use, resulting in the same circuit that we found originally with the same physical qubits.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Understand [Transpilation default settings and configuration options.](defaults-and-configuration-options)
|
|
||||||
- Review the [Commonly used parameters for transpilation](common-parameters) topic.
|
|
||||||
- Try the [Submit transpiled circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) tutorial.
|
|
||||||
- See the [Transpile API documentation.](/api/qiskit/transpiler)
|
|
||||||
</Admonition>
|
|
|
@ -1,169 +0,0 @@
|
||||||
---
|
|
||||||
title: Set transpiler optimization level
|
|
||||||
description: Learn how to set the optimization level
|
|
||||||
---
|
|
||||||
|
|
||||||
# Set the optimization level
|
|
||||||
|
|
||||||
Decomposing quantum circuits into the basis gate set of the target device and the addition of SWAP gates needed to match hardware topology causes an increase in the depth and gate count of quantum circuits. To mitigate this increased complexity, you can set the `optimization_level`. Setting this value calls an optimization routine that optimizes the transpilation process by combining or eliminating gates and by optionally using algorithms to find an optimal layout (depending on the level chosen).
|
|
||||||
|
|
||||||
In some cases these methods are so effective the output circuits have lower depth than the inputs. In other cases, not much can be done, and the computation may be difficult to perform on noisy devices. Choosing the best optimization level might take trial and error, as it depends heavily on the circuit being transpiled and the system being targeted.
|
|
||||||
|
|
||||||
Higher optimization levels generate more optimized circuits at the expense of longer compile times. By default, `optimization_level=1` is used.
|
|
||||||
|
|
||||||
- `optimization_level=0`: Trivial optimization, which maps the circuit to the system with no explicit optimization.
|
|
||||||
- `optimization_level=1-3`: Increasingly complex optimization, with heuristic algorithms that are used to find a layout and insert SWAP gates, with the goal of improving the overall performance of the circuit. The number of iterations that these algorithms run increases with higher optimization levels.
|
|
||||||
|
|
||||||
Because finding the best layout is an NP-hard problem, it is the most time-consuming part of the transpilation process. However, Qiskit uses stochastic algorithms that have been refactored into Rust, resulting in significant speedup. Therefore, optimization levels 1-3 all use the same layout algorithms. There are some slight differences in how the circuits are translated into basis gates, as described in the following table:
|
|
||||||
|
|
||||||
<Table>
|
|
||||||
<thead>
|
|
||||||
<Tr>
|
|
||||||
<Th>Optimization Level</Th>
|
|
||||||
<Th>Description</Th>
|
|
||||||
</Tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<Tr>
|
|
||||||
<Td>0</Td>
|
|
||||||
<Td>
|
|
||||||
No optimization: typically used for hardware characterization
|
|
||||||
- Basic translation
|
|
||||||
- Layout/Routing: `TrivialLayout`, where it selects the same physical qubit numbers as virtual and inserts SWAPs to make it work (using `StochasticSwap`)
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
<Tr>
|
|
||||||
<Td>1</Td>
|
|
||||||
<Td>
|
|
||||||
Light optimization (default):
|
|
||||||
- Layout/Routing: Layout is first attempted with `TrivialLayout`. If additional SWAPs are required, a layout with a minimum number of SWAPs is found by using `SabreSWAP`, then it uses `VF2LayoutPostLayout` to try to select the best qubits in the graph.
|
|
||||||
- InverseCancellelation
|
|
||||||
- 1Q gate optimization
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
<Tr>
|
|
||||||
<Td>2</Td>
|
|
||||||
<Td>
|
|
||||||
Medium optimization:
|
|
||||||
- Layout/Routing: Optimization level 1 (without trivial) + heuristic optimized with greater
|
|
||||||
search depth and trials of optimization function. Because `TrivialLayout` is not used, there is no attempt to use the same physical and virtual qubit numbers.
|
|
||||||
- Commutative cancelation
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
<Tr>
|
|
||||||
<Td>3</Td>
|
|
||||||
<Td>
|
|
||||||
High Optimization:
|
|
||||||
- Optimization level 2 + heuristic optimized on layout/routing further with greater effort/trials
|
|
||||||
- Resynthesis of two-qubit blocks using [Cartan's KAK Decomposition](https://arxiv.org/abs/quant-ph/0507171).
|
|
||||||
- Unitarity-breaking passes:
|
|
||||||
* `OptimizeSwapBeforeMeasure`: Moves the measurements around to avoid SWAPs
|
|
||||||
* `RemoveDiagonalGatesBeforeMeasure`: Removes gates before measurements that would not effect the measurements
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
## Optimization level in action
|
|
||||||
|
|
||||||
Since CX is the noisiest gate, we can quantify the transpilation's "hardware efficiency" by counting the CX gates in the resulting circuit. We will compare the default transpilation levels given the same circuit.
|
|
||||||
|
|
||||||
First, import the necessary libraries:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import transpile, QuantumCircuit
|
|
||||||
from qiskit.circuit.library import UnitaryGate
|
|
||||||
from qiskit.providers.fake_provider import FakeTokyo
|
|
||||||
from qiskit.quantum_info import Operator, random_unitary
|
|
||||||
from qiskit.quantum_info.synthesis.two_qubit_decompose import trace_to_fid
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
```
|
|
||||||
|
|
||||||
Next we build a quantum circuit consisting of a random unitary followed by a SWAP gate. The `random_unitary` method is seeded to ensure reproducible results.
|
|
||||||
|
|
||||||
```python
|
|
||||||
UU = random_unitary(4, seed=12345)
|
|
||||||
rand_U = UnitaryGate(UU)
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.append(rand_U, range(2))
|
|
||||||
qc.swap(0, 1)
|
|
||||||
qc.draw('mpl')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Original abstract circuit](/images/transpile/defaults-and-configuration-options/abstract-circ.png "Original abstract circuit")
|
|
||||||
|
|
||||||
We use `FakeTokyo` as the system and transpile using `optimization_level=1` (the default). To avoid considering the effect of idle qubits, We override the system's coupling map so that the transpiled circuit returns to a two-qubit circuit.
|
|
||||||
|
|
||||||
```python
|
|
||||||
backend = FakeTokyo()
|
|
||||||
qc_t1_exact = transpile(qc, backend, optimization_level=1, coupling_map=[[0, 1], [1, 0]], seed_transpiler=12345)
|
|
||||||
qc_t1_exact.draw('mpl', style='iqp')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Circuit transpiled with optimization level 1](/images/transpile/defaults-and-configuration-options/circ-opt-level-1.png "Circuit transpiled with optimization level 1")
|
|
||||||
|
|
||||||
The transpiled circuit has six CX gates and several `U3` gates, which have much lower error than CX's, so we don't need to count them.
|
|
||||||
|
|
||||||
Repeat for optimization level 2:
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t2_exact = transpile(qc, backend, optimization_level=2, coupling_map=[[0, 1], [1, 0]], seed_transpiler=12345)
|
|
||||||
qc_t2_exact.draw('mpl', style='iqp')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Circuit transpiled with optimization level 2](/images/transpile/defaults-and-configuration-options/circ-opt-level-2.png "Circuit transpiled with optimization level 2")
|
|
||||||
|
|
||||||
This yields the same results as optimization level 1. Note that increasing the level of optimization does not always make a difference.
|
|
||||||
|
|
||||||
Repeat again, with optimization level 3:
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t3_exact = transpile(qc, backend, optimization_level=3, coupling_map=[[0, 1], [1, 0]], seed_transpiler=12345)
|
|
||||||
qc_t3_exact.draw('mpl', style='iqp')
|
|
||||||
```
|
|
||||||
|
|
||||||
![Circuit transpiled with optimization level 3](/images/transpile/defaults-and-configuration-options/circ-opt-level-3.png "Circuit transpiled with optimization level 3")
|
|
||||||
|
|
||||||
Now there are only three CX gates. This is because with optimization level 3, Qiskit tries to re-synthesize two-qubit blocks of gates. Since any two-qubit gate requires at most three CX gates, we get the above result. We can get even fewer CX gates if we sacrifice the fidelity of this synthese by setting `approximation_degree` to a value less than 1:
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_t3_approx = transpile(qc, backend, optimization_level=3, approximation_degree=0.99, coupling_map=[[0, 1], [1, 0]], seed_transpiler=12345)
|
|
||||||
qc_t3_approx.draw('mpl', style='iqp')
|
|
||||||
```
|
|
||||||
|
|
||||||
This circuit has only two CX gates. However, this is an approximate circuit, so we need to understand the difference in fidelity to the desired circuit with the incurred error from running on noisy qubits. We can calculate the fidelity of the approximate circuit:
|
|
||||||
|
|
||||||
```python
|
|
||||||
exact_fid = trace_to_fid(np.trace(np.dot(Operator(qc_t3_exact).adjoint().data, UU)))
|
|
||||||
approx_fid = trace_to_fid(np.trace(np.dot(Operator(qc_t3_approx).adjoint().data, UU)))
|
|
||||||
print(f'Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}')
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
Synthesis fidelity
|
|
||||||
Exact: 1.000
|
|
||||||
Approximate: 0.992
|
|
||||||
```
|
|
||||||
|
|
||||||
Adjusting the optimization level can change other aspects of the circuit too, not just the number of CX gates. For examples of how setting optimization level changes the layout, see [Representing quantum computers](representing_quantum_computers).
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendation">
|
|
||||||
- [Default options and configuration settings](defaults-and-configuration-options)
|
|
||||||
- [Commonly used parameters](common-parameters)
|
|
||||||
- Try the [Submit transpiled circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) tutorial.
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- To learn how to use the `transpile` function, start with the [Transpilation default settings and configuration options](defaults-and-configuration-options) topic.
|
|
||||||
- Continue learning about transpilation with the [Transpiler stages](transpiler-stages) topic.
|
|
||||||
- Try the [Submit transpiled circuits](https://learning.quantum.ibm.com/tutorial/submit-transpiled-circuits) tutorial.
|
|
||||||
- Try the [Build repetition codes](https://learning.quantum.ibm.com/tutorial/build-repetition-codes) tutorial.
|
|
||||||
- See the [Transpile API documentation.](/api/qiskit/transpiler)
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Verify",
|
|
||||||
"collapsed": true,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Introduction",
|
|
||||||
"url": "/verify"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Exact simulation with Qiskit primitives",
|
|
||||||
"url": "/verify/simulate-with-qiskit-primitives"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Exact and noisy simulation with Qiskit Aer primitives",
|
|
||||||
"url": "/verify/simulate-with-qiskit-aer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Build noise models",
|
|
||||||
"url": "/verify/building_noise_models"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Efficient simulation of stabilizer circuits with Qiskit Aer primitives",
|
|
||||||
"url": "/verify/stabilizer-circuit-simulation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "IBM Quantum cloud-based simulators",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Using IBM Quantum cloud-based simulators",
|
|
||||||
"url": "/verify/using-ibm-quantum-simulators"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Available IBM Quantum simulators",
|
|
||||||
"url": "/verify/cloud-based-simulators"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -1,176 +0,0 @@
|
||||||
---
|
|
||||||
title: Available IBM Quantum simulators
|
|
||||||
description: Overview of available IBM Quantum cloud-based simulators
|
|
||||||
---
|
|
||||||
|
|
||||||
# Available IBM Quantum simulators
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
This page gives details about the IBM Quantum cloud-based simulators. For information about the Qiskit built-in simulator, see the [Python-based simulators page in the API reference.](../api/qiskit/providers_basicaer) You can also use the [Qiskit reference primitives](simulate-with-qiskit-primitives) for local statevector simulation.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
IBM Quantum features a collection of high-performance simulators for prototyping quantum circuits and algorithms.
|
|
||||||
|
|
||||||
To view available simulators, on the upper right corner of the screen, click the Application switcher ( ![Application switcher icon](/images/migration/switcher-small2.png) ), select **Compute resources** to view the [Compute resources page,](https://quantum.ibm.com/services/resources?services=simulators) then click All simulators.
|
|
||||||
|
|
||||||
The following simulation methods support a maximum of 300 circuits and 8192 shots per job. Find more information on each simulator below, including its type, a description, the number of qubits it simulates, whether it includes noise modeling, a list of supported gates, and how to call it using Qiskit Runtime. The `simulator_statevector` is a good default choice since it is a general-purpose solution method.
|
|
||||||
|
|
||||||
<Admonition type="info" title="Simulator timeout limit">
|
|
||||||
To prevent the simulators from processing jobs that would otherwise not finish processing in a reasonable amount of time, jobs sent to the simulators are limited to run times under 10,000 seconds (\~2.75 hours).
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
## Statevector simulator
|
|
||||||
|
|
||||||
**Type:** Schrödinger wavefunction
|
|
||||||
|
|
||||||
**Name:** simulator_statevector
|
|
||||||
|
|
||||||
Simulates a quantum circuit by computing the wavefunction of the qubit’s statevector as gates and instructions are applied. Supports general noise modeling.
|
|
||||||
|
|
||||||
**Qubits:** 32
|
|
||||||
|
|
||||||
**Noise modeling:** Yes
|
|
||||||
|
|
||||||
**Supported gates / instructions**
|
|
||||||
|
|
||||||
```python
|
|
||||||
['u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id',
|
|
||||||
'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 't', 'tdg', 'swap',
|
|
||||||
'cx', 'cy', 'cz', 'csx', 'cp', 'cu1', 'cu2', 'cu3', 'rxx',
|
|
||||||
'ryy', 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz',
|
|
||||||
'mcsx', 'mcp', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry',
|
|
||||||
'mcrz', 'mcr', 'mcswap', 'unitary', 'diagonal',
|
|
||||||
'multiplexer', 'initialize', 'kraus', 'roerror', 'delay']
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code example**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.get_backend("simulator_statevector")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Stabilizer simulator
|
|
||||||
|
|
||||||
**Type:** Clifford
|
|
||||||
|
|
||||||
**Name:** simulator_stabilizer
|
|
||||||
|
|
||||||
An efficient simulator of Clifford circuits. Can simulate noisy evolution if the noise operators are also Clifford gates.
|
|
||||||
|
|
||||||
**Qubits:** 5000
|
|
||||||
|
|
||||||
**Noise modeling:** Yes (Clifford only)
|
|
||||||
|
|
||||||
**Supported gates / instructions**
|
|
||||||
|
|
||||||
```python
|
|
||||||
['cx', 'cy', 'cz', 'id', 'x', 'y', 'z', 'h',
|
|
||||||
's', 'sdg', 'sx', 'swap', 'delay', 'roerror']
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code example**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.get_backend("simulator_stabilizer")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Extended stabilizer simulator
|
|
||||||
|
|
||||||
**Type:** Extended Clifford (e.g., Clifford+T)
|
|
||||||
|
|
||||||
**Name:** simulator_extended_stabilizer
|
|
||||||
|
|
||||||
Approximates the action of a quantum circuit using a ranked-stabilizer decomposition. The number of non-Clifford gates determines the number of stabilizer terms.
|
|
||||||
|
|
||||||
**Qubits:** 63
|
|
||||||
|
|
||||||
**Noise modeling:** No
|
|
||||||
|
|
||||||
**Supported gates / instructions**
|
|
||||||
|
|
||||||
```python
|
|
||||||
['u0', 'u1', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h',
|
|
||||||
't', 'tdg', 's', 'sdg', 'sx', 'swap', 'p', 'ccx', 'ccz',
|
|
||||||
'delay', 'roerror']
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code example**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.get_backend("simulator_extended_stabilizer")
|
|
||||||
```
|
|
||||||
|
|
||||||
## MPS simulator
|
|
||||||
|
|
||||||
**Type:** Matrix Product State
|
|
||||||
|
|
||||||
**Name:** simulator_mps
|
|
||||||
|
|
||||||
A tensor-network simulator that uses a Matrix Product State (MPS) representation for states. This representation is often more efficient for states with weak entanglement.
|
|
||||||
|
|
||||||
**Qubits:** 100
|
|
||||||
|
|
||||||
**Noise modeling:** No
|
|
||||||
|
|
||||||
**Supported gates / instructions**
|
|
||||||
|
|
||||||
```python
|
|
||||||
['unitary', 't', 'tdg', 'id', 'cp', 'u1', 'u2', 'u3', 'u',
|
|
||||||
'cx', 'cz', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'swap',
|
|
||||||
'p', 'ccx', 'delay', 'roerror']
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code example**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.get_backend("simulator_mps")
|
|
||||||
```
|
|
||||||
|
|
||||||
## QASM simulator
|
|
||||||
|
|
||||||
**Type:** General, context-aware
|
|
||||||
|
|
||||||
**Name:** ibmq_qasm_simulator
|
|
||||||
|
|
||||||
A general-purpose simulator for simulating quantum circuits both ideally and subject to noise modeling. The simulation method is automatically selected based on the input circuits and parameters.
|
|
||||||
|
|
||||||
**Qubits:** 32
|
|
||||||
|
|
||||||
**Noise modeling:** Yes
|
|
||||||
|
|
||||||
**Supported gates / instructions**
|
|
||||||
|
|
||||||
```python
|
|
||||||
['u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id',
|
|
||||||
'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 't', 'tdg', 'swap',
|
|
||||||
'cx', 'cy', 'cz', 'csx', 'cp', 'cu1', 'cu2', 'cu3', 'rxx',
|
|
||||||
'ryy', 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz',
|
|
||||||
'mcsx', 'mcp', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry',
|
|
||||||
'mcrz', 'mcr', 'mcswap', 'unitary', 'diagonal',
|
|
||||||
'multiplexer', 'initialize', 'kraus', 'roerror', 'delay']
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code example**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
backend = service.get_backend("ibmq_qasm_simulator")
|
|
||||||
```
|
|
||||||
|
|
||||||
Qiskit built-in simulator, see the [Python-based simulators API](/api/qiskit/providers_basicaer) reference.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Learn about simulators built into Qiskit in the [Python-based simulators API](/api/qiskit/providers_basicaer) reference.
|
|
||||||
- Discover available systems in the [System information](../run/system-information) topic.
|
|
||||||
</Admonition>
|
|
|
@ -1,21 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduction
|
|
||||||
description: Introduction to the Verify phase
|
|
||||||
---
|
|
||||||
|
|
||||||
# Introduction
|
|
||||||
|
|
||||||
In the verify phase, you test your quantum programs by running them on simulated devices and exploring their performance under realistic device noise models. This allows you to validate them before sending them to a physical system.
|
|
||||||
|
|
||||||
Because the cost of classically simulating quantum circuits scales exponentially with the number of qubits, circuits that are larger than 50 qubits or so generally cannot be directly verified. For such circuits, you can:
|
|
||||||
|
|
||||||
- Test smaller versions of the circuits that can be simulated classically.
|
|
||||||
- Modify the circuits so that they become classically simulable and test these modified circuits.
|
|
||||||
|
|
||||||
Stabilizer circuits are a useful tool for accomplishing this latter goal. These are a restricted class of quantum circuits that can be efficiently simulated classically. Specialized simulators can easily simulate stabilizer circuits with thousands of qubits. See [Efficient simulation of stabilizer circuits with Qiskit Aer primitives](stabilizer-circuit-simulation) for an overview of stabilizer circuits and how to simulate them efficiently.
|
|
||||||
|
|
||||||
For general quantum circuits, the following tools are available for you to verify your quantum programs:
|
|
||||||
|
|
||||||
- For exact simulation of small quantum circuits, you can use the reference primitives included with Qiskit. See [Exact simulation with Qiskit primitives](simulate-with-qiskit-primitives).
|
|
||||||
- For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, use [Qiskit Aer](https://qiskit.org/ecosystem/aer/), a project that is part of the [Qiskit Ecosystem](https://qiskit.github.io/ecosystem/). See [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer).
|
|
||||||
- To build your own custom noise models, use the [`noise`](https://qiskit.org/ecosystem/aer/apidocs/aer_noise.html) module of Qiskit Aer. See [Building noise models](building_noise_models).
|
|
File diff suppressed because one or more lines are too long
|
@ -1,466 +0,0 @@
|
||||||
---
|
|
||||||
title: Exact simulation with Qiskit primitives
|
|
||||||
description: Simulate with Qiskit reference primitives. How to compute an expectation value with the Estimator primitive, and how to compute circuit output probabilities with the Sampler primitive
|
|
||||||
---
|
|
||||||
|
|
||||||
# Exact simulation with Qiskit primitives
|
|
||||||
|
|
||||||
The reference primitives in Qiskit can perform local statevector simulations, which is useful for quickly prototyping algorithms.
|
|
||||||
|
|
||||||
The `Estimator` primitive can compute an expectation value, and the `Sampler` primitive can compute circuit output probabilities.
|
|
||||||
|
|
||||||
## Compute an expectation value with the `Estimator` primitive
|
|
||||||
|
|
||||||
Follow these instructions to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
While this guide uses Qiskit’s reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import BackendEstimator
|
|
||||||
from <some_qiskit_provider> import QiskitProvider
|
|
||||||
|
|
||||||
provider = QiskitProvider()
|
|
||||||
backend = provider.get_backend('backend_name')
|
|
||||||
estimator = BackendEstimator(backend)
|
|
||||||
```
|
|
||||||
|
|
||||||
There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem/#primitives) for more details).
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Initialize observables
|
|
||||||
|
|
||||||
The first step is to define the observables whose expected value you want to compute. Each observable can be any `BaseOperator`, like the operators from [`qiskit.quantum_info`](../api/qiskit/quantum_info).
|
|
||||||
Among them it is preferable to use [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1])
|
|
||||||
```
|
|
||||||
|
|
||||||
### Initialize QuantumCircuit
|
|
||||||
|
|
||||||
Next, create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) for which you want to obtain the expected value.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.h(0)
|
|
||||||
qc.cx(0,1)
|
|
||||||
qc.draw("mpl")
|
|
||||||
```
|
|
||||||
|
|
||||||
![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png "Initial QuantumCircuit")
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) must not include any measurements.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Initialize `Estimator`
|
|
||||||
|
|
||||||
Next, instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Estimator
|
|
||||||
|
|
||||||
estimator = Estimator()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run and get results
|
|
||||||
|
|
||||||
Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method,
|
|
||||||
which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object)
|
|
||||||
with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.
|
|
||||||
|
|
||||||
```python
|
|
||||||
job = estimator.run(qc, observable)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
EstimatorResult(values=array([4.]), metadata=[{}])
|
|
||||||
```
|
|
||||||
|
|
||||||
This example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable. If you want to get expectation values for multiple circuits and observables, you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length.
|
|
||||||
|
|
||||||
#### Get the expected value
|
|
||||||
|
|
||||||
From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values).
|
|
||||||
|
|
||||||
[`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray`
|
|
||||||
whose `i`<sup>th</sup> element is the expectation value corresponding to the `i`<sup>th</sup> circuit and `i`<sup>th</sup> observable.
|
|
||||||
|
|
||||||
```python
|
|
||||||
exp_value = result.values[0]
|
|
||||||
print(exp_value)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
3.999999999999999
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameterized circuit with `Estimator`
|
|
||||||
|
|
||||||
The [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive can be run with unbound parameterized circuits like the one below.
|
|
||||||
You can also manually bind values to the parameters of the circuit and follow the steps of the previous example.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit import Parameter
|
|
||||||
|
|
||||||
theta = Parameter('θ')
|
|
||||||
param_qc = QuantumCircuit(2)
|
|
||||||
param_qc.ry(theta, 0)
|
|
||||||
param_qc.cx(0,1)
|
|
||||||
print(param_qc.draw())
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
┌───────┐
|
|
||||||
q_0: ┤ Ry(θ) ├──■──
|
|
||||||
└───────┘┌─┴─┐
|
|
||||||
q_1: ─────────┤ X ├
|
|
||||||
└───┘
|
|
||||||
```
|
|
||||||
|
|
||||||
The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s.
|
|
||||||
The `i`<sup>th</sup> element of the outer `list` is the set of parameter values that corresponds to the `i`<sup>th</sup> circuit and observable.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
parameter_values = [[0], [np.pi/6], [np.pi/2]]
|
|
||||||
|
|
||||||
job = estimator.run([param_qc]*3, [observable]*3, parameter_values=parameter_values)
|
|
||||||
values = job.result().values
|
|
||||||
|
|
||||||
for i in range(3):
|
|
||||||
print(f"Parameter: {parameter_values[i][0]:.5f}\t Expectation value: {values[i]}")
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Parameter: 0.00000 Expectation value: 2.0
|
|
||||||
Parameter: 0.52360 Expectation value: 3.0
|
|
||||||
Parameter: 1.57080 Expectation value: 4.0
|
|
||||||
```
|
|
||||||
|
|
||||||
### Change run options
|
|
||||||
|
|
||||||
Your workflow might require tuning primitive run options, such as the number of shots.
|
|
||||||
|
|
||||||
By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact statevector calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be modified to include shot noise if the number of `shots` is set. For reproducibility purposes, a `seed` will also be set in the following examples.
|
|
||||||
|
|
||||||
There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator):
|
|
||||||
|
|
||||||
- Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.
|
|
||||||
- Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.
|
|
||||||
|
|
||||||
#### Set keyword arguments for [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run)
|
|
||||||
|
|
||||||
If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by passing them as keyword arguments.
|
|
||||||
|
|
||||||
```python
|
|
||||||
job = estimator.run(qc, observable, shots=2048, seed=123)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
print(result.values[0])
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
3.999999998697238
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options
|
|
||||||
|
|
||||||
If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. That way you can use the same [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) object as many times as you wish without having to
|
|
||||||
rewrite the configuration values every time you use [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run).
|
|
||||||
|
|
||||||
#### Modify existing [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator)
|
|
||||||
|
|
||||||
If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments.
|
|
||||||
|
|
||||||
```python
|
|
||||||
estimator.set_options(shots=2048, seed=123)
|
|
||||||
|
|
||||||
job = estimator.run(qc, observable)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
print(result.values[0])
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
3.999999998697238
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the options
|
|
||||||
|
|
||||||
If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, define a `dict` like this one:
|
|
||||||
|
|
||||||
```python
|
|
||||||
options = {"shots": 2048, "seed": 123}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can then introduce it into your new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the `options` argument.
|
|
||||||
|
|
||||||
```python
|
|
||||||
estimator = Estimator(options=options)
|
|
||||||
|
|
||||||
job = estimator.run(qc, observable)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
print(result.values[0])
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
3.999999998697238
|
|
||||||
```
|
|
||||||
|
|
||||||
## Compute circuit output probabilities with `Sampler` primitive
|
|
||||||
|
|
||||||
Follow these instructions to get the probability distribution of a quantum circuit with the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
While this guide uses Qiskit’s reference implementation, the `Sampler` primitive can be run with any provider using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler).
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import BackendSampler
|
|
||||||
from <some_qiskit_provider> import QiskitProvider
|
|
||||||
|
|
||||||
provider = QiskitProvider()
|
|
||||||
backend = provider.get_backend('backend_name')
|
|
||||||
sampler = BackendSampler(backend)
|
|
||||||
```
|
|
||||||
|
|
||||||
There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details).
|
|
||||||
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Initialize QuantumCircuit
|
|
||||||
|
|
||||||
The first step is to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s from which you want to obtain the probability distribution.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2)
|
|
||||||
qc.h(0)
|
|
||||||
qc.cx(0,1)
|
|
||||||
qc.measure_all()
|
|
||||||
qc.draw("mpl")
|
|
||||||
```
|
|
||||||
|
|
||||||
![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png "Initial QuantumCircuit")
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) must include measurements.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
### Initialize `Sampler`
|
|
||||||
|
|
||||||
Next, create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.primitives import Sampler
|
|
||||||
|
|
||||||
sampler = Sampler()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run and get results
|
|
||||||
|
|
||||||
Now that you have defined your `sampler`, run it by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.
|
|
||||||
|
|
||||||
```python
|
|
||||||
job = sampler.run(qc)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}])
|
|
||||||
```
|
|
||||||
|
|
||||||
While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), you can sample multiple circuits by passing a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.
|
|
||||||
|
|
||||||
### Get the probability distribution
|
|
||||||
|
|
||||||
From these results you can extract the quasi-probability distributions with the attribute [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists).
|
|
||||||
|
|
||||||
Even though there is only one circuit in this example, [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists) returns a list of [`qiskit.result.QuasiDistribution`](../api/qiskit/qiskit.result.QuasiDistribution)s.
|
|
||||||
`result.quasi_dists[i]` is the quasi-probability distribution of the `i`<sup>th</sup> circuit.
|
|
||||||
|
|
||||||
<Admonition type="note">
|
|
||||||
A quasi-probability distribution differs from a probability distribution in that negative values are also allowed.
|
|
||||||
However, the quasi-probabilities must sum up to 1 like probabilities.
|
|
||||||
Negative quasi-probabilities may appear when using error mitigation techniques.
|
|
||||||
</Admonition>
|
|
||||||
|
|
||||||
```python
|
|
||||||
quasi_dist = result.quasi_dists[0]
|
|
||||||
print(quasi_dist)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
{0: 0.4999999999999999, 3: 0.4999999999999999}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Probability distribution with binary outputs
|
|
||||||
|
|
||||||
If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method.
|
|
||||||
|
|
||||||
```python
|
|
||||||
print(quasi_dist.binary_probabilities())
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
{'00': 0.4999999999999999, '11': 0.4999999999999999}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameterized circuit with `Sampler`
|
|
||||||
|
|
||||||
The [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive can be run with unbound parameterized circuits like the one below.
|
|
||||||
You can also manually bind values to the parameters of the circuit and follow the steps of the previous example.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit import Parameter
|
|
||||||
|
|
||||||
theta = Parameter('θ')
|
|
||||||
param_qc = QuantumCircuit(2)
|
|
||||||
param_qc.ry(theta, 0)
|
|
||||||
param_qc.cx(0,1)
|
|
||||||
param_qc.measure_all()
|
|
||||||
print(param_qc.draw())
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
┌───────┐ ░ ┌─┐
|
|
||||||
q_0: ┤ Ry(θ) ├──■───░─┤M├───
|
|
||||||
└───────┘┌─┴─┐ ░ └╥┘┌─┐
|
|
||||||
q_1: ─────────┤ X ├─░──╫─┤M├
|
|
||||||
└───┘ ░ ║ └╥┘
|
|
||||||
meas: 2/══════════════════╩══╩═
|
|
||||||
0 1
|
|
||||||
```
|
|
||||||
|
|
||||||
The main difference from the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. The `i`<sup>th</sup> element of the outer `list` is the set of parameter values that corresponds to the `i`<sup>th</sup> circuit.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
parameter_values = [[0], [np.pi/6], [np.pi/2]]
|
|
||||||
|
|
||||||
job = sampler.run([param_qc]*3, parameter_values=parameter_values)
|
|
||||||
dists = job.result().quasi_dists
|
|
||||||
|
|
||||||
for i in range(3):
|
|
||||||
print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}")
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Parameter: 0.00000 Probabilities: {0: 1.0}
|
|
||||||
Parameter: 0.52360 Probabilities: {0: 0.9330127018922194, 3: 0.0669872981077807}
|
|
||||||
Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.4999999999999999}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Change run options
|
|
||||||
|
|
||||||
Your workflow might require tuning primitive run options, such as the number of shots.
|
|
||||||
|
|
||||||
By default, the reference [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class performs an exact statevector
|
|
||||||
calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be
|
|
||||||
modified to include shot noise if the number of `shots` is set.
|
|
||||||
For reproducibility purposes, a `seed` will also be set in the following examples.
|
|
||||||
|
|
||||||
There are two main ways of setting options in the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler):
|
|
||||||
|
|
||||||
- Set keyword arguments in the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.
|
|
||||||
- Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.
|
|
||||||
|
|
||||||
#### Set keyword arguments for [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)
|
|
||||||
|
|
||||||
If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by passing them as keyword arguments.
|
|
||||||
|
|
||||||
```python
|
|
||||||
job = sampler.run(qc, shots=2048, seed=123)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options
|
|
||||||
|
|
||||||
If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run).
|
|
||||||
|
|
||||||
#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler)
|
|
||||||
|
|
||||||
If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use [`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments.
|
|
||||||
|
|
||||||
```python
|
|
||||||
sampler.set_options(shots=2048, seed=123)
|
|
||||||
|
|
||||||
job = sampler.run(qc)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options
|
|
||||||
|
|
||||||
If you prefer to define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options, define a `dict` like this one:
|
|
||||||
|
|
||||||
```python
|
|
||||||
options = {"shots": 2048, "seed": 123}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can then introduce it into your new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the `options` argument.
|
|
||||||
|
|
||||||
```python
|
|
||||||
sampler = Sampler(options=options)
|
|
||||||
|
|
||||||
job = sampler.run(qc)
|
|
||||||
result = job.result()
|
|
||||||
print(result)
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer).
|
|
||||||
- To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial.
|
|
||||||
- Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference.
|
|
||||||
- Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference.
|
|
||||||
- Learn how to run on a physical system in the [Run](../run) section.
|
|
||||||
</Admonition>
|
|
File diff suppressed because one or more lines are too long
|
@ -1,318 +0,0 @@
|
||||||
---
|
|
||||||
title: Using IBM Quantum cloud-based simulators
|
|
||||||
description: Set up ibmq_qasm_simulator and map a basic noise model for an IBM Quantum hardware device in Qiskit Runtime.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Using IBM Quantum cloud-based simulators
|
|
||||||
|
|
||||||
Set up `ibmq_qasm_simulator` and map a basic noise model for an IBM Quantum hardware device in Qiskit Runtime, then use this noise model to perform noisy simulations of `QuantumCircuits` by using `Sampler` and `Estimator` to study the effects of errors that occur on real devices.
|
|
||||||
|
|
||||||
## Set up your local development environment
|
|
||||||
|
|
||||||
If you haven’t already set up a Qiskit Runtime service instance, follow the steps in [Install and set up](../start/install) to do so.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# load necessary Runtime libraries
|
|
||||||
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Estimator, Session, Options
|
|
||||||
|
|
||||||
service = QiskitRuntimeService()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Prepare the environment
|
|
||||||
|
|
||||||
First, we run an example routine. One of the major benefits of using primitives is simplification of binding multiple parameters in parameterized circuits. To illustrate this, we start with is an example circuit with a controlled [P-gate](/api/qiskit/qiskit.circuit.library.PhaseGate) as implemented in the following code. Here, we parameterize the `P-gate` with a rotation parameter `theta`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.circuit import Parameter
|
|
||||||
from qiskit import QuantumCircuit
|
|
||||||
|
|
||||||
theta = Parameter('theta')
|
|
||||||
|
|
||||||
qc = QuantumCircuit(2,1)
|
|
||||||
qc.x(1)
|
|
||||||
qc.h(0)
|
|
||||||
qc.cp(theta,0,1)
|
|
||||||
qc.h(0)
|
|
||||||
qc.measure(0,0)
|
|
||||||
|
|
||||||
qc.draw('mpl')
|
|
||||||
```
|
|
||||||
|
|
||||||
![](/images/qiskit-ibm-runtime/noisy-sim-circuit.png)
|
|
||||||
|
|
||||||
The circuit shown previously is parameterized and the eigenvalue is put back into qubit 0 to be measured. The eigenvalue's rotation is determined by the parameter theta. Next, we define the circuit's parameters as a list. The parameters in this example range from $0$ to $2\\pi$, divided over 50 evenly spaced points.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
phases = np.linspace(0, 2*np.pi, 50)
|
|
||||||
|
|
||||||
# phases need to be expressed as a list of lists
|
|
||||||
individual_phases = [[phase] for phase in phases]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running on the ideal simulator
|
|
||||||
|
|
||||||
### Set the backend and options to use
|
|
||||||
|
|
||||||
Our first run assumes an ideal case, without any `noise_model`, `optimization_level` or `resilience_level` for both Sampler and Estimator. We will define the options in the following code:
|
|
||||||
|
|
||||||
```python
|
|
||||||
backend = "ibmq_qasm_simulator" # use the simulator
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
options = Options()
|
|
||||||
options.simulator.seed_simulator = 42
|
|
||||||
options.execution.shots = 1000
|
|
||||||
options.optimization_level = 0 # no optimization
|
|
||||||
options.resilience_level = 0 # no error mitigation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run the circuits on Sampler
|
|
||||||
|
|
||||||
Next, we use the Sampler primitive to sample the circuit and get the resultant quasi-probability distribution. Visit the [Get started with Sampler](../run/primitives-get-started#get-started-with-sampler) section for more information about the Sampler primitive.
|
|
||||||
|
|
||||||
```python
|
|
||||||
sampler = Sampler(options=options, backend=backend)
|
|
||||||
job = sampler.run(
|
|
||||||
circuits=[qc]*len(phases),
|
|
||||||
parameter_values=individual_phases
|
|
||||||
)
|
|
||||||
result = job.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
# the probablity of being in the 1 state for each of these values
|
|
||||||
prob_values = [dist.get(1, 0) for dist in result.quasi_dists]
|
|
||||||
|
|
||||||
plt.plot(phases, prob_values, 'o', label='Simulator')
|
|
||||||
plt.plot(phases, np.sin(phases/2,)**2, label='Theory')
|
|
||||||
plt.xlabel('Phase')
|
|
||||||
plt.ylabel('Probability')
|
|
||||||
plt.legend()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
<matplotlib.legend.Legend at 0x7f7fd233b6d0>
|
|
||||||
```
|
|
||||||
|
|
||||||
![This image shows that the value found by the simulator is very close to the theoretical value.](/images/qiskit-ibm-runtime/noisy-sim-sampler-ideal.png "Simulated versus theoretical value")
|
|
||||||
|
|
||||||
### Run the circuits on Estimator
|
|
||||||
|
|
||||||
Visit the [Get started with Estimator](../run/primitives-get-started#get-started-with-estimator) section for more information on the Estimator primitive.
|
|
||||||
|
|
||||||
The Estimator binds single-qubit rotations to get Hamiltonians before it returns expectation values of quantum operators. Therefore, the circuit doesn’t require any measurements. Currently the circuit `qc` has measurements, so we will remove these with `remove_final_measurements`.
|
|
||||||
|
|
||||||
```python
|
|
||||||
qc_no_meas = qc.remove_final_measurements(inplace=False)
|
|
||||||
qc_no_meas.draw('mpl')
|
|
||||||
```
|
|
||||||
|
|
||||||
![](/images/qiskit-ibm-runtime/noisy-sim-estimator-circuit.png)
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from qiskit.quantum_info import SparsePauliOp
|
|
||||||
|
|
||||||
ZZ = SparsePauliOp.from_list([("ZZ", 1)])
|
|
||||||
print(f" > Observable: {ZZ.paulis}")
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
> Observable: ['ZZ']
|
|
||||||
```
|
|
||||||
|
|
||||||
With this observable, the expectation value is calculated by the
|
|
||||||
following equation.
|
|
||||||
|
|
||||||
$$ \\langle ZZ\\rangle =\\langle \\psi | ZZ | \\psi\\rangle=\\langle \\psi|(|0\\rangle\\langle 0| -|1\\rangle\\langle 1|)\\otimes(|0\\rangle\\langle 0| - |1\\rangle\\langle 1|) |\\psi\\rangle =|\\langle 00|\\psi\\rangle|^2 - |\\langle 01 | \\psi\\rangle|^2 - |\\langle 10 | \\psi\\rangle|^2 + |\\langle 11|\\psi\\rangle|^2$$
|
|
||||||
|
|
||||||
The following code implements the expectation value equation.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend=backend):
|
|
||||||
estimator = Estimator(options=options)
|
|
||||||
job = estimator.run(
|
|
||||||
circuits=[qc_no_meas]*len(phases),
|
|
||||||
parameter_values=individual_phases,
|
|
||||||
observables=[ZZ]*len(phases)
|
|
||||||
)
|
|
||||||
result = job.result()
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
exp_values = result.values
|
|
||||||
|
|
||||||
plt.plot(phases, exp_values, 'o', label='Simulator')
|
|
||||||
plt.plot(phases, 2*np.sin(phases/2)**2-1, label='Theory')
|
|
||||||
plt.xlabel('Phase')
|
|
||||||
plt.ylabel('Expectation')
|
|
||||||
plt.legend()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
<matplotlib.legend.Legend at 0x7f7fd0ed8820>
|
|
||||||
```
|
|
||||||
|
|
||||||
![This image shows that the value found by the simulator is very close to the theoretical value.](/images/qiskit-ibm-runtime/noisy-sim-estimator-ideal.png "Simulated versus theoretical values")
|
|
||||||
|
|
||||||
## Running a noisy simulation
|
|
||||||
|
|
||||||
Now we’ll set up our simulator to run a noisy simulation rather than the ideal one. We can pass a custom `noise_model` to the Qiskit Runtime simulator by specifying it in the `Options` parameter. Here we will try to mimic a real backend by using the `noise_model` from a `FakeBackend` class. The noise model can be extracted from the `FakeBackend` and passed as a `simulator` parameter in options. For more details, visit the [Fake Provider](/api/qiskit/providers_fake_provider) documentation in the Qiskit Terra API reference.
|
|
||||||
|
|
||||||
Since we are trying to mimic a real backend, we can also pass in the backend topology's `coupling_map` and its supported `basis_gates` to have a more realistic noisy simulation.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.providers.fake_provider import FakeManila
|
|
||||||
from qiskit_aer.noise import NoiseModel
|
|
||||||
|
|
||||||
# Make a noise model
|
|
||||||
fake_backend = FakeManila()
|
|
||||||
noise_model = NoiseModel.from_backend(fake_backend)
|
|
||||||
|
|
||||||
# Set options to include the noise model
|
|
||||||
options = Options()
|
|
||||||
options.simulator = {
|
|
||||||
"noise_model": noise_model,
|
|
||||||
"basis_gates": fake_backend.configuration().basis_gates,
|
|
||||||
"coupling_map": fake_backend.configuration().coupling_map,
|
|
||||||
"seed_simulator": 42
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set number of shots, optimization_level and resilience_level
|
|
||||||
options.execution.shots = 1000
|
|
||||||
options.optimization_level = 0
|
|
||||||
options.resilience_level = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
The `ibmq_qasm_simulator` allows for the activation of the `resilience_levels` offered by the Qiskit Runtime service, and use of these levels on simulators is best demonstrated using the noisy simulation as we have described previously.
|
|
||||||
|
|
||||||
To illustrate the comparison, we will define two set of `Options`. Here, `options` is set to `resilience level = 0` to represent a normal run without error mitigation, and `options with em` is set to `resilience level = 1` to represent a run with error mitigation enabled.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Set options to include the noise model with error mitigation
|
|
||||||
options_with_em = Options()
|
|
||||||
options_with_em.simulator = {
|
|
||||||
"noise_model": noise_model,
|
|
||||||
"basis_gates": fake_backend.configuration().basis_gates,
|
|
||||||
"coupling_map": fake_backend.configuration().coupling_map,
|
|
||||||
"seed_simulator": 42
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set number of shots, optimization_level and resilience_level
|
|
||||||
options_with_em.execution.shots = 1000
|
|
||||||
options_with_em.optimization_level = 0 # no optimization
|
|
||||||
options_with_em.resilience_level = 1 # M3 for Sampler and T-REx for Estimator
|
|
||||||
```
|
|
||||||
|
|
||||||
When you set the `resilience_level` to 1, M3 is activated in Sampler.
|
|
||||||
All available resilience level configurations are described on the [Configure error mitigation](../run/configure-error-mitigation) page.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend=backend):
|
|
||||||
# include the noise model without M3
|
|
||||||
sampler = Sampler(options=options)
|
|
||||||
job = sampler.run(
|
|
||||||
circuits=[qc]*len(phases),
|
|
||||||
parameter_values=individual_phases
|
|
||||||
)
|
|
||||||
result = job.result()
|
|
||||||
prob_values = [1-dist[0] for dist in result.quasi_dists]
|
|
||||||
|
|
||||||
# include the noise model with M3
|
|
||||||
sampler = Sampler(options=options_with_em)
|
|
||||||
job = sampler.run(
|
|
||||||
circuits=[qc]*len(phases),
|
|
||||||
parameter_values=individual_phases
|
|
||||||
)
|
|
||||||
result = job.result()
|
|
||||||
prob_values_with_em = [1-dist[0] for dist in result.quasi_dists]
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
plt.plot(phases, prob_values, 'o', label='Noisy')
|
|
||||||
plt.plot(phases, prob_values_with_em, 'o', label='Mitigated')
|
|
||||||
plt.plot(phases, np.sin(phases/2,)**2, label='Theory')
|
|
||||||
plt.xlabel('Phase')
|
|
||||||
plt.ylabel('Probability')
|
|
||||||
plt.legend()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
<matplotlib.legend.Legend at 0x7f7fb4230700>
|
|
||||||
```
|
|
||||||
|
|
||||||
![This image shows that the value found by a "noisy" simulator is not very close to the theoretical value, but the approximation is better when mitigated by using M3.](/images/qiskit-ibm-runtime/noisy-sim-sampler-noisy.png "Noisy and mitigated (M3) values versus theoretical values")
|
|
||||||
|
|
||||||
`T-REx` is triggered in Estimator when the resilience level is set to
|
|
||||||
|
|
||||||
1.
|
|
||||||
|
|
||||||
```python
|
|
||||||
with Session(service=service, backend=backend):
|
|
||||||
# include the noise model without T-REx
|
|
||||||
estimator = Estimator(options=options)
|
|
||||||
job = estimator.run(
|
|
||||||
circuits=[qc_no_meas]*len(phases),
|
|
||||||
parameter_values=individual_phases,
|
|
||||||
observables=[ZZ]*len(phases)
|
|
||||||
)
|
|
||||||
result = job.result()
|
|
||||||
exp_values = result.values
|
|
||||||
|
|
||||||
# include the noise model with T-REx
|
|
||||||
estimator = Estimator(options=options_with_em)
|
|
||||||
job = estimator.run(
|
|
||||||
circuits=[qc_no_meas]*len(phases),
|
|
||||||
parameter_values=individual_phases,
|
|
||||||
observables=[ZZ]*len(phases))
|
|
||||||
result = job.result()
|
|
||||||
exp_values_with_em = result.values
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
plt.plot(phases, exp_values, 'o', label='Noisy')
|
|
||||||
plt.plot(phases, exp_values_with_em, 'o', label='Mitigated')
|
|
||||||
plt.plot(phases, 2*np.sin(phases/2)**2-1, label='Theory')
|
|
||||||
plt.xlabel('Phase')
|
|
||||||
plt.ylabel('Expectation')
|
|
||||||
plt.legend()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
<matplotlib.legend.Legend at 0x7f7f7006ca00>
|
|
||||||
```
|
|
||||||
|
|
||||||
![This image shows that the value found by a "noisy" simulator is not very close to the theoretical value, but the approximation is better when mitigated by using T-REX.](/images/qiskit-ibm-runtime/noisy-sim-estimator-noisy.png "Noisy and mitigated (T-REX) values versus theoretical values")
|
|
||||||
|
|
||||||
Resilience levels are currently in beta so sampling overhead and
|
|
||||||
solution quality will vary from circuit to circuit. New features,
|
|
||||||
advanced options, and management tools will be released on a rolling
|
|
||||||
basis. You can also test out higher levels of resilience and
|
|
||||||
explore the additional options they offer. For more information
|
|
||||||
about activating features like `Digital-ZNE` and `PEC`, in addition to `M3` and `T-REx` as shown in the previous examples, see the [Error suppression and error mitigation with Qiskit Runtime](https://learning.quantum.ibm.com/tutorial/error-suppression-and-error-mitigation-with-qiskit-runtime) tutorial.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import qiskit_ibm_runtime
|
|
||||||
qiskit_ibm_runtime.version.get_version_info()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
'0.8.0'
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
from qiskit.tools.jupyter import *
|
|
||||||
%qiskit_version_table
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
<Admonition type="tip" title="Recommendations">
|
|
||||||
- Learn about Qiskit Runtime error mitigation in [Exact and noisy simulation with Qiskit Aer primitives](../run/configure-error-mitigation).
|
|
||||||
- Explore error mitigation options in the [Cost Functions](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions) course.
|
|
||||||
</Admonition>
|
|
Loading…
Reference in New Issue