Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration guide for providers to implement V2 primitives #2496

Merged
merged 43 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fa864d7
Initial content proposal
ElePT Dec 17, 2024
aa48513
Test push
beckykd Dec 17, 2024
a77b070
Simplify code snippets, edit introduction text, add placeholders for …
ElePT Dec 17, 2024
15a72bb
Merge branch 'EPT/primitives-migration-for-providers' of https://gith…
ElePT Dec 17, 2024
f86e387
Add links
beckykd Dec 17, 2024
4941f0d
more links, qiskit bot, TOC
beckykd Dec 17, 2024
11a469a
local links
beckykd Dec 17, 2024
45328ae
edits
beckykd Dec 17, 2024
0edf399
add link
beckykd Dec 17, 2024
38fe250
Apply suggestions from code review
beckykd Dec 17, 2024
1b0ad76
Apply suggestions from code review
beckykd Dec 17, 2024
7d87696
Update docs/migration-guides/external-providers-primitives-v2.mdx
beckykd Dec 17, 2024
ebb7b5b
Add comment to explain type checking change in BackendEstimator example
ElePT Dec 18, 2024
55c4a24
Apply Jessie's suggestions for the motivation section
ElePT Dec 19, 2024
3812adf
Address #2543
beckykd Jan 21, 2025
671ee42
edits
beckykd Jan 22, 2025
b2f2d0b
Update docs/migration-guides/qiskit-runtime-from-third-party-provider…
ElePT Jan 28, 2025
218fc46
Merge branch 'main' into EPT/primitives-migration-for-providers
arnaucasau Jan 30, 2025
3faaf9d
Apply Jessie's review suggestions. Refactor backend primitives topic,…
ElePT Mar 10, 2025
701bd74
Merge branch 'main' of https://github.com/Qiskit/documentation into E…
ElePT Mar 10, 2025
2553d8a
Update code examples in external providers guide, apply Jessie's feed…
ElePT Mar 10, 2025
be23e07
Fix typos
ElePT Mar 10, 2025
00f71ad
Rename title
ElePT Mar 10, 2025
049a58c
Fix links
ElePT Mar 10, 2025
6fdc22d
Fix links again
ElePT Mar 10, 2025
dff711c
copyedit
abbycross Mar 10, 2025
91422bf
copyedit
abbycross Mar 10, 2025
a23051f
copyedit
abbycross Mar 10, 2025
ba8f23c
Apply suggestions from code review
abbycross Mar 10, 2025
24a72c9
Restructure overview
ElePT Mar 11, 2025
476f7b8
Apply suggestions from Jessie's code review
ElePT Mar 11, 2025
864999e
Merge branch 'EPT/primitives-migration-for-providers' of https://gith…
ElePT Mar 11, 2025
e4c8774
Finish applying comments from Jessie's code review
ElePT Mar 11, 2025
02f42c3
Apply suggestions from code review
ElePT Mar 11, 2025
f91edea
Apply suggestions from code review
abbycross Mar 11, 2025
7a372aa
Update docs/migration-guides/external-providers-primitives-v2.mdx
ElePT Mar 11, 2025
b9771d8
rmv parens for consistency
abbycross Mar 11, 2025
6c63139
Apply suggestions from Jessie's code review
ElePT Mar 12, 2025
28e4009
Update docs/migration-guides/external-providers-primitives-v2.mdx
abbycross Mar 12, 2025
14ece72
Fix titles and parenthesis
beckykd Mar 12, 2025
a93d831
Edits
beckykd Mar 12, 2025
aa97f9e
Edits
beckykd Mar 12, 2025
b7bfa7b
Update docs/migration-guides/qiskit-runtime.mdx
ElePT Mar 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions docs/migration-guides/external-providers-primitives-v2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,51 @@ description: Migrate to the primitives interface in external providers

## Why should third-party providers implement primitives?

The evolution of [user access patterns for QPUs](/migration-guides/qiskit-runtime#why-migrate-to-qiskit-runtime-primitives?)
has led to the `backend.run` interface being superseded by the Qiskit Primitives (`Sampler` and `Estimator`).
The Qiskit SDK is built to support third parties in creating external providers of quantum resources.
The evolution of [user access patterns for QPUs](/migration-guides/qiskit-runtime#why-migrate-to-qiskit-runtime-primitives)
has led to the Qiskit primitives (`Sampler` and `Estimator`) superseding the `backend.run` interface.
To ensure users of Qiskit can seamlessly transition between providers, we encourage all third-party providers
to implement native support of the primitives for performant access to their hardware or simulators.

After a period of overlap between `backend.run` and primitives where users have gradually transitioned to the
primitives access model, the `qiskit-ibm-runtime` provider has finally discontinued access to IBM QPUs through `backend.run`.
This guide is for you if the following applies:

This guide is for you if you are in charge of a third-party provider, your interface is still based on `backend.run`,
and you are looking for guidance to implement your own native `Sampler` and `Estimator` primitives.
This will enable users whose code is based on primitives to seamlessly transition between providers.
- You are in charge of a third-party provider
- Your interface is still based on `backend.run`
- You are looking for guidance to implement your own native `Sampler` and `Estimator` primitives

Once you have migrated your interface to primitives, your users with primitives-based code can seamlessly transition between providers.

## Exposing custom `Sampler` and `Estimator` implementations

Custom primitive implementations can be used to wrap any service provider hardware access function
(for example: `execute_workload(QPU)` or `resource.access()`) or local simulator,
as long as the final inputs and outputs conform to the established standards set by the primitive interfaces.
## Exposing native `Sampler` and `Estimator` implementations

Depending on the scope of your provider and what workflows you want to enable, you can choose to implement
instances of any of the abstract base primitive interfaces: ([BaseEstimatorV2](/api/qiskit/qiskit.primitives.BaseEstimatorV2)
and/or [BaseSamplerV2](/api/qiskit/qiskit.primitives.BaseSamplerV2)). The `Estimator` interfaces exposes a tool to calculate
expectation values of observables with respect to quantum states, while the `Sampler` outputs the counts or probability distributions
obtained from sampling from a quantum state in a QPU. The base interfaces provide methods for execution, querying job status,
and returning the job results. See the `qiskit.primitives` [API documentation](link) for more information.
Qiskit defines base interfaces ([BaseEstimatorV2](/api/qiskit/qiskit.primitives.BaseEstimatorV2)
and [BaseSamplerV2](/api/qiskit/qiskit.primitives.BaseSamplerV2)) that set the standards for input and output handling
in the primitives. Native primitive implementations can be developed to wrap any service provider hardware access function
(for example, `execute_workload(QPU)` or `resource.access()`) or local simulator,
as long as the final inputs and outputs conform to the established standards set by the base interfaces.

Once you know which primitive to implement, you should review the PUB data model for input and output handling. See the following
guide for more details on [PUBs](/guides/primitive-input-output#pubs). To handle job status and results,
the Qiskit SDK provides [`DataBin`](../api/qiskit/qiskit.primitives.DataBin),
[`PubResult`](../api/qiskit/qiskit.primitives.PubResult), [`PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult),
and [`BasePrimitiveJob`](../api/qiskit/qiskit.primitives.BasePrimitiveJob) objects.
The `Estimator` interface exposes a tool to calculate expectation
values of observables with respect to quantum states, while the `Sampler` outputs the counts or probability distributions
obtained from sampling from a quantum state in a QPU. These base interfaces also provide standard methods for execution,
querying job status, and returning the job results. See the `qiskit.primitives` [API documentation](/api/qiskit/primitives)
for more information.

The Primitive Unified Bloc (PUB) data model defines the input format to the primitives, as described in
[Overview of PUBs](https://qiskit.github.io/documentation/pr-2496/guides/primitive-input-output#pubs).
While different types of data can be accepted into a PUB, both `SamplerPub` and `EstimatorPub` have a `coerce()`
method that can be used to convert them into the respective model. The code snippets below provide an
example for each of the primitives.

An example of custom `Sampler` implementation for a third-party provider may look like:
The [PrimitiveResult](https://qiskit.github.io/documentation/pr-2496/api/qiskit/qiskit.primitives.PrimitiveResult)
defines the output of a primitive job. It is comprised of additional data models such as
[PubResult](https://qiskit.github.io/documentation/pr-2496/api/qiskit/qiskit.primitives.PubResult) and
[DataBin](https://qiskit.github.io/documentation/pr-2496/api/qiskit/qiskit.primitives.DataBin).
See [Overview of primitive results](https://docs.quantum.ibm.com/guides/primitive-input-output#overview-of-primitive-results)
for more information.

## Example of third-party `Sampler` implementation

An example of custom `Sampler` implementation for a third-party provider might look like:

``` python
from qiskit.primitives import (
Expand Down Expand Up @@ -144,9 +157,11 @@ class CustomSampler(BaseSamplerV2):
```

This implementation is based on the [`StatevectorSampler` source code](/api/qiskit/qiskit.primitives.StatevectorSampler),
with some additions to represent the backend/hardware resource access, as the `StatevectorSampler` class is designed for local statevector simulator.
with some additions to represent the backend/hardware resource access, as the `StatevectorSampler` class is designed for local statevector simulators.

## Example of third-party `Estimator` implementation

An example of custom `Estimator` implementation for a third-party provider may look like:
An example of custom `Estimator` implementation for a third-party provider might look like:

``` python
from .base import BaseEstimatorV2
Expand Down Expand Up @@ -248,5 +263,5 @@ class CustomEstimator(BaseEstimatorV2):
)
```

Similarly to the `Sampler` example, this implementation is based on the [`StatevectorEstimator` source code](/api/qiskit/qiskit.primitives.StatevectorEstimator),
with some additions to represent the backend/hardware resource access, as the `StatevectorEstimator` class is designed for local statevector simulator.
Similar to the `Sampler` example, this implementation is based on the [`StatevectorEstimator` source code](/api/qiskit/qiskit.primitives.StatevectorEstimator),
with some additions to represent the backend/hardware resource access, as the `StatevectorEstimator` class is designed for local statevector simulators.
51 changes: 23 additions & 28 deletions docs/migration-guides/qiskit-backend-primitives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,36 @@ description: Migrate to primitives for users of third-party providers with `back

# Migrate to primitives for users of third-party providers with `backend.run`

The `backend.run()` interface, previously the primary access point for IBM QPUs, has been superseded
by the Qiskit [primitives interface](/guides/primitives) in `qiskit_ibm_runtime`.
While this has become the standard for IBM providers, not all third-party providers have transitioned
to the primitives framework, and `backend.run()` remains in Qiskit for backward compatibility.
The `backend.run` interface was the primary access point to quantum hardware and simulators offered by third party providers that integrate with Qiskit. The evolution of [user access patterns for QPUs](/migration-guides/qiskit-runtime#why-migrate-to-qiskit-runtime-primitives) has led to the Qiskit primitives (Sampler and Estimator) superseding this interface. However, not all third-party providers have transitioned to the primitives framework, and `backend.run()` remains in Qiskit for backward compatibility.

This guide is for you if you have written or want to write code using `Sampler` and `Estimator`
primitives but need to interact with a provider that still relies on `backend.run()`. If you are a
provider developer looking to implement and expose your own `Sampler` and
`Estimator` primitives, you can find guidance [here](/migration-guides/external-providers-primitives-v2).
`Estimator` primitives, you can find guidance in the [Migrate provider interfaces from backend.run to primitives](/migration-guides/external-providers-primitives-v2) guide.

For providers that don't expose native primitives, the Qiskit SDK offers wrappers for `backend.run` that can
used out-of the box: the [`BackendSamplerV2`.](/api/qiskit/qiskit.primitives.BackendSamplerV2) and
For providers that don't expose native primitives, the Qiskit SDK offers wrappers for `backend.run` that you can
use out-of the box: the [`BackendSamplerV2`.](/api/qiskit/qiskit.primitives.BackendSamplerV2) and
[`BackendEstimatorV2`](/api/qiskit/qiskit.primitives.BackendEstimatorV2) classes.

If you are already familiar with the [`SamplerV2`](sampler-v2 "qiskit_ibm_runtime.SamplerV2")
and [`EstimatorV2`](estimator-v2 "qiskit_ibm_runtime.EstimatorV2") interfaces, the transition to
If you are already familiar with the [`SamplerV2`](/api/qiskit-ibm-runtime/sampler-v2)
and [`EstimatorV2`](/api/qiskit-ibm-runtime/estimator-v2) interfaces, the transition to
[`BackendSamplerV2`.](/api/qiskit/qiskit.primitives.BackendSamplerV2) and
[`BackendEstimatorV2`](/api/qiskit/qiskit.primitives.BackendEstimatorV2) is seamless, as
these classes follow the same usage patterns. The inputs to the primitives should follow
the Primitive Unified Bloc (PUB) syntax, and the output formats will follow the
V2 primitives standard. See the [Overview of PUBs section](/guides/primitive-input-output#pubs) in
the Primitive inputs and outputs guide for details.

The two main differences with the implementations of [`SamplerV2`](sampler-v2 "qiskit_ibm_runtime.SamplerV2")
and [`EstimatorV2`](estimator-v2 "qiskit_ibm_runtime.EstimatorV2") are:

1. the `backend` input passed during the "backend primitive" instantiation. This input argument will allow to
internally wrap the access to the internal provider through `backend.run()` and it should not be confused
with the `mode` input argument of [`SamplerV2`](sampler-v2 "qiskit_ibm_runtime.SamplerV2")
and [`EstimatorV2`](estimator-v2 "qiskit_ibm_runtime.EstimatorV2").

2. the use of `options`, which contains one more level of nesting compared to provider-specific primitives and
is initially provided as a `dict` instead of an `Options` instance.
The first level of nesting includes (`default_shots`, `seed_simulator` and `run_options`) for the `BackendSamplerV2`
and (`default_precision`, `abelian_grouping`, `seed_simulator` and `run_options`) for the `BackendEstimatorV2`.
the Primitive Unified Bloc (PUB) syntax, and the output formats should follow the
`PrimitiveResult` interface. See the [Primitive inputs and outputs](/guides/primitive-input-output) for more details.

The two main differences with the implementations of [`SamplerV2`](/api/qiskit-ibm-runtime/sampler-v2)
and [`EstimatorV2`](/api/qiskit-ibm-runtime/estimator-v2) are:

1. The `backend` input passed during the "backend primitive" instantiation. This input argument allows access
to the internal provider through `backend.run()` and should not be confused
with the `mode` input argument of [`SamplerV2`](/api/qiskit-ibm-runtime/sampler-v2)
and [`EstimatorV2`](/api/qiskit-ibm-runtime/estimator-v2).

2. What `options` can be set. Options should be provided as a `dict` instead of an `Options` instance.
`BackendSamplerV2` includes `default_shots`, `seed_simulator` and `run_options`;
`BackendEstimatorV2` includes `default_precision`, `abelian_grouping`, `seed_simulator` and `run_options`.
The `run_options` field defines the options to pass through to the `.run()` method of the wrapped backend instance.

Note that because these wrappers are independent of `qiskit_ibm_runtime`, they do not offer access to execution
Expand All @@ -52,7 +47,7 @@ strategy that is not covered by the out-of-the-box wrapper, it is always possibl
[`BackendEstimatorV2`](/api/qiskit/qiskit.primitives.BackendEstimatorV2) interfaces through subclassing to fit the specific
interface needs.

Here is an example usage of the [`BackendEstimatorV2`](/api/qiskit/qiskit.primitives.BackendEstimatorV2)
The following is an example usage of the [`BackendSamplerV2`](/api/qiskit/qiskit.primitives.BackendSamplerV2)
class with a fictional third-party provider backend that only implements `backend.run()`:

``` python
Expand All @@ -75,5 +70,5 @@ pm = generate_preset_pass_manager(backend=backend)
tqc = pm.run(qc)

# run using pub syntax
result = sampler.run(([qc])).result()
```
result = sampler.run([qc]).result()
```
37 changes: 15 additions & 22 deletions docs/migration-guides/qiskit-runtime.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ examples to help you migrate code from the legacy `backend.run()` interface to u
- Because both `backend.run()` and the "version 1" primitives are being deprecated, this guide uses only the V2 primitives.
</Admonition>

The `qiskit-ibm-runtime` package provides cloud access to the IBM QPUs (quantum processing units) through the primitives interface. The `backend.run()` interface coexisted with the original (V1) primitives model as the dedicated “direct hardware access” entry point. With the introduction of the V2 primitives interface, the new `SamplerV2` class now fulfills that role. Consequentially, `backend.run()` is being deprecated, along with `qiskit-ibm-provider`, which only exposed the `backend.run()` interface.
The `qiskit-ibm-runtime` package provides cloud access to the IBM&reg; QPUs (quantum processing units) through the primitives interface. The `backend.run()` interface coexisted with the original (V1) primitives model as the dedicated “direct hardware access” entry point. With the introduction of the V2 primitives interface, the new `SamplerV2` class now fulfills that role. Consequentially, `backend.run()` and `qiskit-ibm-provider`, which only exposed the `backend.run()` interface, are no longer supported.

The Qiskit Runtime primitives implement the reference Sampler V2 and Estimator V2 interfaces found in `qiskit.primitives`, and enable capabilities not available with the legacy `backend.run()` interface. These capabilities include application of advanced processing techniques for error suppression and mitigation in Estimator, the ability to efficiently sweep between arrays of parameter value sets or observables in both Sampler and Estimator, and access to the new local testing mode. Additionally, Qiskit Runtime lets users run iterative algorithm circuits back to back (session mode) or in collections of circuits without having to re-queue each job (batch mode). This results in more efficient quantum processor use and reduces the time spent running complex computations.

Expand All @@ -26,19 +26,18 @@ The Qiskit Runtime primitives implement the reference Sampler V2 and Estimator V
Similar to the early days of classical computers, when developers had to manipulate CPU registers directly,
the early interface to QPUs simply returned the raw data coming out of the control electronics.
This was not a huge issue when QPUs lived in labs and only allowed direct access by researchers.
When IBM first brought its QPUs to the cloud, we recognized most developers would not and
should not be familiar with distilling such raw data into 0s and 1s. Therefore,
we introduced `backend.run`, our first abstraction for accessing QPUs. This allowed developers
to operate on a data format they were more familiar with and focus on the bigger picture.
Acknowledging that most developers would not and should not be familiar with distilling such raw data into
0s and 1s, IBM introduced `backend.run`, a first abstraction for accessing QPUs in the cloud. This allowed developers
to operate on a familiar data format and focus on the bigger picture.

As access to QPUs became more widespread, and with more quantum algorithms being developed,
we again recognized the need for a higher-level abstraction. This led to the introduction of
again the need for a higher-level abstraction emerged. In response, IBM introduced
the Qiskit [primitives interface](/guides/primitives), which are optimized for two core tasks in quantum algorithm development:
expectation value estimation (Estimator) and circuit sampling (Sampler). The goal is once
again to help developers to focus more on innovation and less on data conversion.

For backward compatibility, the `backend.run` interface continues to exist in Qiskit. However, it is deprecated
in Qiskit Runtime, as most of the IBM Quantum users have migrated to V2 primitives due to their improved
For backward compatibility, the `backend.run` interface continues to exist in Qiskit. However, it is no longer supported
in Qiskit Runtime after the deprecation period, as most IBM Quantum&reg; users have migrated to V2 primitives due to their improved
usability and efficiency.

## Basic steps to migrate to primitives
Expand All @@ -64,30 +63,24 @@ Follow the steps in the appropriate topic to change your import options and othe
- [Migrate from `qiskit-ibm-provider`](qiskit-runtime-from-ibm-provider)
- [Migrate from `qiskit-ibmq-provider`](qiskit-runtime-from-ibmq-provider)

### Step 3: Replace the call to `backend.run` with a call to `qiskit_ibm_runtime`.
### Step 3: Replace the call to `backend.run` with a call to primitives.

See these topics for instructions:
See these topics for instructions if you are using `qiskit-ibm-runtime`:

- [Update code that performs circuit sampling](qiskit-runtime-examples#sampler-algorithm)
- [Update code that calculates expectation values](qiskit-runtime-examples#estimator-algorithm)
- [Common use cases (basic, parameterized, and dynamic circuits)](qiskit-runtime-use-case)
- Replace any `backend.run` options with `qiskit_ibm_runtime` options:
- [Migrate options](qiskit-runtime-options)
- Common use cases [Options section](qiskit-runtime-use-case#migrate-options)

### Step 3a: Replace any `backend.run` options with `qiskit_ibm_runtime` options.

See the following topics for instructions:

- [Migrate options](qiskit-runtime-options)
- Common use cases [Options section](qiskit-runtime-use-case#migrate-options)

### Step 3b: If you want to access a 3rd-party provider that only exposes `backend.run`, you can still follow a primitive-compatible your workflow using the Qiskit backend primitives.

See the following topic for instructions:
See the following topic for instructions if you are using a 3rd-party provider that only exposes `backend.run`:

- [Migrate using backend primitives](qiskit-backend-primitives)

## Information to share with your users

There is already a collection of migration guides for users to help with the following tasks:
The following migration guides can help users with the following tasks:

- [Transition to the Qiskit Runtime provider](/migration-guides/qiskit-runtime)
- [Update user code to the V2 primitives interface](/migration-guides/v2-primitives)
Expand All @@ -102,4 +95,4 @@ There is already a collection of migration guides for users to help with the fol
- [Run a primitive in a batch](/guides/run-jobs-batch)
- Experiment with the [Submit pre-transpiled circuits tutorial](https://learning.quantum.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives)

</Admonition>
</Admonition>