Update examples in get-started-with-primitives (#2200)

Closes #2189 and is part of #2094

---------

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
Co-authored-by: Frank Harkins <frankharkins@hotmail.co.uk>
Co-authored-by: Rebecca Dimock <66339736+beckykd@users.noreply.github.com>
This commit is contained in:
abbycross 2024-10-31 14:58:17 -04:00 committed by GitHub
parent 38a4dfac91
commit 4144d6047d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 485 additions and 237 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,237 +0,0 @@
---
title: Get started with primitives
description: How to use the Estimator and Sampler primitives in Qiskit Runtime.
---
# Get started with primitives
The steps in this topic describes how to set up primitives, explore the options you can use to configure them, and invoke them in a program.
<Admonition type="note">
While this documentation uses the primitives from Qiskit Runtime, which allow you to use IBM&reg; backends, the primitives can be run on any provider by using the [backend primitives](#backend) instead. Additionally, you can use the *reference* primitives to run on a local statevector simulator. See [Exact simulation with Qiskit primitives](simulate-with-qiskit-sdk-primitives) for details.
</Admonition>
<span id="start-estimator"></span>
## Get started with Estimator
{/*Verified the v2 examples 2/29 */}
### 1. Initialize the account
Because Qiskit Runtime Estimator is a managed service, you first need to initialize your account. You can then select the QPU you want to use to calculate the expectation value.
Follow the steps in the [Install and set up topic](install-qiskit) if you don't already have an account.
```python
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
estimator = Estimator(mode=backend)
```
### 2. Create a circuit and an observable
You 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.transpiler.preset_passmanagers import generate_preset_pass_manager
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}")
```
Output
```text
>>> Observable: ['ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ...']
```
The circuit and observable need to be transformed to only use instructions supported by the QPU (referred to as *instruction set architecture (ISA)* circuits). We'll use the transpiler to do this.
```python
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
```
### 3. Initialize Qiskit Runtime Estimator
When you initialize the Estimator, use the `mode` parameter to specify the mode you want it to run in. Possible values are `batch`, `session`, or `backend` objects for batch, session, and job execution mode, respectively. For more information, see [Introduction to Qiskit Runtime execution modes.](execution-modes)
```python
from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(mode=backend)
```
### 4. Invoke the Estimator and get results
Next, invoke the `run()` method to calculate expectation values for the input circuits and observables. The circuit, observable, and optional parameter value sets are input as *primitive unified bloc* (PUB) tuples.
```python
job = estimator.run([(isa_circuit, isa_observable)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
```
Output
```text
>>> Job ID: 8874203f-f5a0-4491-b093-3f29a1adcae4
>>> Job Status: JobStatus.RUNNING
```
```python
result = job.result()
print(f">>> {result}")
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")
```
Output
```text
>>> PrimitiveResult([PubResult(data=DataBin<>(evs=0.013671875, stds=0.0156235396179561), metadata={'target_precision': 0.015625})], metadata={})
> Expectation value: 0.013671875
> Metadata: {'target_precision': 0.015625}
```
<span id="start-sampler"></span>
## Get started with Sampler
### 1. Initialize the account
Because Qiskit Runtime Sampler is a managed service, you first need to initialize your account. You can then select the QPU you want to use to calculate the expectation value.
Follow the steps in the [Install and set up topic](install-qiskit) if you don't already have an account set up.
```python
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
```
### 2. Create a circuit
You 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.transpiler.preset_passmanagers import generate_preset_pass_manager
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()
```
Use the transpiler to get an ISA circuit.
```python
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
```
### 3. Initialize the Qiskit Runtime Sampler
When you initialize the Sampler, use the `mode` parameter to specify the mode you want it to run in. Possible values are `batch`, `session`, or `backend` objects for batch, session, and job execution mode, respectively. For more information, see [Introduction to Qiskit Runtime execution modes.](execution-modes)
```python
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
```
### 4. Invoke the Sampler and get results
Next, invoke the `run()` method to generate the output. The circuit and optional parameter value sets are input as *primitive unified bloc* (PUB) tuples.
```python
job = sampler.run([isa_circuit])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
```
Output
```text
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edced
>>> Job Status: JobStatus.RUNNING
```
```python
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
print(f"Counts for the meas output register: {pub_result.data.meas.get_counts()}")
```
Output
```text
Counts for the meas output register: {'0111': 50, '0000': 243, '0001': 101, '0101': 93, '0100': 188, '0011': 128, '1011': 22, '0110': 13, '1100': 10, '1000': 24, '0010': 29, '1010': 26, '1101': 20, '1110': 45, '1001': 16, '1111': 16}
```
<span id="backend"></span>
## Get started with the backend primitives
Unlike provider-specific primitives, backend primitives are generic implementations that can be used with an arbitrary
`backend` object, as long as it implements the [`Backend`](/api/qiskit/qiskit.providers.Backend) interface.
- The Sampler primitive can be run with any provider by using [`qiskit.primitives.BackendSamplerV2`](/api/qiskit/qiskit.primitives.BackendSamplerV2).
- The Estimator primitive can be run with any provider by using [`qiskit.primitives.BackendEstimatorV2`](../api/qiskit/qiskit.primitives.BackendEstimatorV2).
Some providers implement primitives natively. See the [Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#provider) for details.
### Example: BackendEstimator
```python
from qiskit.primitives import BackendEstimatorV2
from <some_qiskit_provider> import QiskitProvider
provider = QiskitProvider()
backend = provider.get_backend('backend_name')
estimator = BackendEstimatorV2(backend)
```
### Example: BackendSampler
```python
from qiskit.primitives import BackendSamplerV2
from <some_qiskit_provider> import QiskitProvider
provider = QiskitProvider()
backend = provider.get_backend('backend_name')
sampler = BackendSamplerV2(backend)
```
### Similarities and differences between backend and Runtime primitives
- The inputs to and outputs from [`qiskit.primitives.BackendSamplerV2`](/api/qiskit/qiskit.primitives.BackendSamplerV2) and [`qiskit.primitives.BackendEstimatorV2`](../api/qiskit/qiskit.primitives.BackendEstimatorV2)
follow the same PUB format as the primitives in Qiskit Runtime. See [Primitive inputs and outputs](primitive-input-output) for details.
However, there can be differences in the fields of the returned metadata.
- The [`qiskit.primitives.BackendEstimatorV2`](/api/qiskit/qiskit.primitives.BackendEstimatorV2) class offers no measurement or gate error mitigation implementations out-of-the-box, as
backend primitives are designed to run locally in the user's machine.
- The [`qiskit.primitives.BackendSamplerV2`](/api/qiskit/qiskit.primitives.BackendSamplerV2) class requires a backend that supports the `memory` option.
- The backend primitive interfaces expose custom [`SamplerV2`](/api/qiskit/qiskit.primitives.BackendSamplerV2) and [`EstimatorV2`](/api/qiskit/qiskit.primitives.BackendEstimatorV2) `Options` that are different from the Runtime implementations.
## Next steps
<Admonition type="tip" title="Recommendations">
- Learn how to [test locally](local-testing-mode) before running on quantum computers.
- 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.
- 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.
- Learn how to [use the primitive options.](runtime-options-overview)
- View the API for [Sampler](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.SamplerOptions) and [Estimator](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.EstimatorOptions) options.
- Read [Migrate to V2 primitives](/migration-guides/v2-primitives).
</Admonition>

View File

@ -56,6 +56,7 @@ notebooks_that_submit_jobs = [
# A job is "too big" if a cell can't run in under 5 mins, or we run out of
# memory on a reasonable device.
notebooks_no_mock = [
"docs/guides/get-started-with-primitives.ipynb",
"docs/guides/hello-world.ipynb",
"docs/guides/serverless-manage-resources.ipynb",
"docs/guides/noise-learning.ipynb"