diff --git a/docs/api/migration-guides/_toc.json b/docs/api/migration-guides/_toc.json
index 443ae6506b2..35b8df98b47 100644
--- a/docs/api/migration-guides/_toc.json
+++ b/docs/api/migration-guides/_toc.json
@@ -23,6 +23,10 @@
}
]
},
+ {
+ "title": "Migrate to the Qiskit Runtime V2 primitives",
+ "url": "/api/migration-guides/v2-primitives"
+ },
{
"title": "Migrate to Qiskit Runtime",
"children": [
diff --git a/docs/api/migration-guides/index.mdx b/docs/api/migration-guides/index.mdx
index 43cfa7dff92..a8248d43cfe 100644
--- a/docs/api/migration-guides/index.mdx
+++ b/docs/api/migration-guides/index.mdx
@@ -11,6 +11,7 @@ These migration guides help you more effectively use Qiskit and Qiskit Runtime:
* Migrate to Qiskit 1.0
* [Qiskit 1.0 packaging changes](/api/migration-guides/qiskit-1.0-installation)
* [Qiskit 1.0 feature changes](/api/migration-guides/qiskit-1.0-features)
+* [Migrate to the Qiskit Runtime V2 primitives](/api/migration-guides/v2-primitives)
* Migrate to Qiskit Runtime
* [How to migrate](./qiskit-runtime)
* [Examples](./qiskit-runtime-examples)
diff --git a/docs/api/migration-guides/v2-primitives.mdx b/docs/api/migration-guides/v2-primitives.mdx
new file mode 100644
index 00000000000..4b097268638
--- /dev/null
+++ b/docs/api/migration-guides/v2-primitives.mdx
@@ -0,0 +1,1193 @@
+---
+title: Migrate to the V2 primitives
+description: Migrate from using the original primitives (Estimator and Sampler) to using the updated V2 primitives (V2 Estimator and V2 Sampler)
+
+---
+
+
+# Migrate to the Qiskit Runtime V2 primitives
+
+This guide describes what changed in the Qiskit Runtime V2 primitives and why, describes each new primitive in detail, and gives examples to help you migrate code from using the legacy primitives to the V2 primitives. The examples in the guide all use the Qiskit Runtime primitives, but in general, the same changes apply to the other primitive implementations. The functions unique to Qiskit Runtime such as error mitigation remain unique to Qiskit Runtime.
+
+For information about the changes to the Qiskit reference primitives (now called *statevector* primitives), see [the qiskit.primitives section](qiskit-1.0-features#qiskit.primitives) in the Qiskit 1.0 feature changes page. See [StatevectorSampler](/api/qiskit/qiskit.primitives.StatevectorSampler) and [StatevectorEstimator](/api/qiskit/qiskit.primitives.StatevectorEstimator) for V2 primitive reference implementations.
+
+## Overview
+
+Version 2 of the primitives is introduced with a new base class for both Sampler and Estimator ([BaseSamplerV2](../api/qiskit/qiskit.primitives.BaseSamplerV2) and [BaseEstimatorV2](../api/qiskit/qiskit.primitives.BaseEstimatorV2)), along with new types for their inputs and outputs.
+
+The new interface lets you specify a single circuit and multiple observables (if using Estimator) and parameter value sets for that circuit, so that sweeps over parameter value sets and observables can be efficiently specified. Previously, you had to specify the same circuit multiple times to match the size of the data to be combined. Also, while you can still use `optimization_level` and `resilience_level` (if using Estimator) as the simple knobs, V2 primitives give you the flexibility to turn on or off individual error mitigation / suppression methods to customize them for your needs.
+
+To reduce the total job execution time, V2 primitives only accept circuits and observables that use instructions supported by the target system (referred to as instruction set architecture (ISA) circuits and observables). V2 primitives do not perform layout, routing, and translation operations but continue to optimize the circuits if you specify `optimization_level>0`. See the [transpilation documentation](../../transpile) for instructions to transform circuits.
+
+V2 Sampler is simplified to focus on its core task of sampling the output register from execution of quantum circuits. It returns the samples, whose type is defined by the program, without weights. The output data is also separated by the output register names defined by the program. This change enables future support for circuits with classical control flow.
+
+
+## Major changes
+
+### Import
+
+For backward compatibility, you must explicity import the V2 primitives. Specifying `import V2 as ` is not required, but makes it easier to transition code to V2.
+
+
+After the V1 primitives are no longer supported, `import ` will import the V2 version of the specified primitive.
+
+
+
+
+ ```python
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import Estimator
+```
+
+
+
+
+
+ ```python
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import Sampler
+```
+
+
+
+
+### Input and output
+
+#### Input
+
+Both `SamplerV2` and `EstimatorV2` take one or more *primitive unified blocs* (PUBs) as the input. Each PUB is a tuple that contains **one** circuit and the data broadcasted to that circuit, which can be multiple observables and parameters. Each PUB returns a result.
+
+* V2 Sampler PUB format: (``, ``, ``), where ``and `` are optional.
+* V2 Estimator PUB format: (``, ``, ``, ``), where ``and `` are optional.
+ Numpy [broadcasting rules](https://numpy.org/doc/stable/user/basics.broadcasting.html) are used when combining observables and parameter values.
+
+Additionally, the following changes have been made:
+
+* V2 Estimator has gained a `precision` argument in the `run()` method that specifies the targeted precision of the expectation value estimates.
+* V2 Sampler has the `shots` argument in its `run()` method.
+
+##### Examples
+
+{/*From the boxnote.*/}
+
+V2 Estimator example that uses precision in `run()`:
+
+```python
+# Estimate expectation values for two PUBs, both with 0.05 precision.
+estimator.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)
+```
+
+V2 Sampler example that uses shots in `run()`:
+
+```python
+# Sample two circuits at 128 shots each.
+sampler.run([(circuit1,), (circuit2,)], shots=128)
+
+# Sample two circuits at different amounts of shots. The "None"s are necessary
+# as placeholders
+# for the lack of parameter values in this example.
+sampler.run([(circuit1, None, 123), (circuit2, None, 456)])
+```
+
+#### Output
+
+The output is now in the [`PubResult`](../api/qiskit/qiskit.primitives.PubResult) format. A `PubResult` is the data and metadata resulting from a single PUB’s execution.
+
+* V2 Estimator continues to return expectation values.
+* The `data` portion of a V2 Estimator PubResult contains both expectation values and standard errors (`stds`). V1 returned variance in metadata.
+* V2 Sampler returns per-shot measurements in the form of **bitstrings**,
+ instead of the quasi-probability distributions from the V1
+ interface. The bitstrings show the measurement outcomes, preserving the shot
+ order in which they were measured.
+* V2 Sampler has convenience methods like `get_counts()` to help with migration.
+* The V2 Sampler result objects organize data in terms of their **input circuits' classical register names**, for
+ compatibility with dynamic circuits. By default, the classical register name is `meas`, as shown in the following example. When defining your circuit, if you create one or more classical registers with a non-default name, you would use that name to get those results.
+
+ ```python
+ # Define a quantum circuit with 2 qubits
+ circuit = QuantumCircuit(2)
+ circuit.h(0)
+ circuit.cx(0, 1)
+ circuit.measure_all()
+ circuit.draw()
+ ```
+ ```text
+ ┌───┐ ░ ┌─┐
+ q_0: ┤ H ├──■───░─┤M├───
+ └───┘┌─┴─┐ ░ └╥┘┌─┐
+ q_1: ─────┤ X ├─░──╫─┤M├
+ └───┘ ░ ║ └╥┘
+ meas: 2/══════════════╩══╩═
+ 0 1
+ ```
+
+#### Estimator examples (input and output)
+
+{/*Verified by Elena.*/}
+
+
+
+ ```python
+ # Estimator V1: Execute 1 circuit with 4 observables
+ job = estimator_v1.run([circuit] * 4, [obs1, obs2, obs3, obs4])
+ evs = job.result().values
+
+ # Estimator V2: Execute 1 circuit with 4 observables
+ job = estimator_v2.run([(circuit, [obs1, obs2, obs3, obs4])])
+ evs = job.result()[0].data.evs
+```
+
+
+
+ ```python
+ # Estimator V1: Execute 1 circuit with 4 observables and 2 parameter sets
+ job = estimator_v1.run([circuit] * 8, [obs1, obs2, obs3, obs4] * 2, [vals1, vals2] * 4)
+ evs = job.result().values
+
+ # Estimator V2: Execute 1 circuit with 4 observables and 2 parameter sets
+
+ job = estimator_v2.run([(circuit, [[obs1], [obs2], [obs3], [obs4]], [[vals1], [vals2]])])
+ evs = job.result()[0].data.evs
+```
+
+
+
+ ```python
+ # Estimator V1: Cannot execute 2 circuits with different observables
+
+ # Estimator V2: Execute 2 circuits with 2 different observables. There are
+ # two PUBs because each PUB can have only one circuit.
+ job = estimator_v2.run([(circuit1, obs1), (circuit2, obs2)])
+ evs1 = job.result()[0].data.evs # result for pub 1 (circuit 1)
+ evs2 = job.result()[1].data.evs # result for pub 2 (circuit 2)
+```
+
+
+
+#### Sampler examples (input and output)
+
+{/*Verified by Elena.*/}
+
+
+
+ ```python
+ # Sampler V1: Execute 1 circuit with 3 parameter sets
+ job = sampler_v1.run([circuit] * 3, [vals1, vals2, vals3])
+ dists = job.result().quasi_dists
+
+ # Sampler V2: Executing 1 circuit with 3 parameter sets
+ job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])
+ counts = job.result()[0].data.meas.get_counts()
+```
+
+
+
+ ```python
+ # Sampler V1: Execute 2 circuits with 1 parameter set
+ job = sampler_v1.run([circuit1, circuit2], [vals1] * 2)
+ dists = job.result().quasi_dists
+
+ # Sampler V2: Execute 2 circuits with 1 parameter set
+ job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])
+ counts1 = job.result()[0].data.meas.get_counts() # result for pub 1 (circuit 1)
+ counts2 = job.result()[1].data.meas.get_counts() # result for pub 2 (circuit 2)
+```
+
+
+
+Example that uses different output registers
+
+{/*From the boxnote.*/}
+
+```python
+from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
+
+alpha = ClassicalRegister(5, "alpha")
+beta = ClassicalRegister(7, "beta")
+qreg = QuantumRegister(12)
+
+circuit = QuantumCircuit(qreg, alpha, beta)
+circuit.h(0)
+circuit.measure(qreg[:5], alpha)
+circuit.measure(qreg[5:], beta)
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=12)
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+sampler = Sampler(backend)
+job = sampler.run([(isa_circuit,)])
+result = job.result()
+# Get results for the first (and only) PUB
+pub_result = result[0]
+print(f" >> Counts for the alpha output register: {pub_result.data.alpha.get_counts()}")
+print(f" >> Counts for the beta output register: {pub_result.data.beta.get_counts()}")
+```
+
+### Options
+
+Options are specified differently in the V2 primitives in these ways:
+
+- `SamplerV2` and `EstimatorV2` now have separate options classes. You can see the available options and update option values during or after primitive initialization.
+- Instead of the `set_options()` method, V2 primitive options have the `update()` method that applies changes to the `options` attribute.
+- If you do not specify a value for an option, it is given a special value of `Unset` and the server defaults are used.
+- For V2 primitives, the `options` attribute is the `dataclass` Python type. You can use the built-in `asdict` method to convert it to a dictionary.
+
+See the [API reference](../api/qiskit-ibm-runtime/options) for the list of available options.
+
+{/*Verified EstimatorV2. 2/23 */}
+
+
+
+ ```python
+from dataclasses import asdict
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+estimator = Estimator(backend, options={"resilience_level": 2})
+
+# Setting options after primitive initialization
+# This uses auto complete.
+estimator.options.optimization_level = 1
+estimator.options.default_shots = 4000
+# This does bulk update.
+estimator.options.update(default_shots=4000, optimization_level=1)
+
+# Print the dictionary format.
+# Server defaults are used for unset options.
+print(asdict(estimator.options))
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+options = Options()
+# This uses auto complete.
+options.resilience_level = 2
+estimator = Estimator(backend=backend, options=options)
+
+# Setting options after primitive initialization.
+# This does bulk update.
+estimator.set_options(shots=4000, optimization_level=1)
+```
+
+
+
+
+
+ ```python
+from dataclasses import asdict
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+sampler = Sampler(backend, options={"default_shots": 4096})
+
+# Setting options after primitive initialization
+# This uses auto complete.
+sampler.options.dynamical_decoupling.enable = True
+# This does bulk update. The value for default_shots is overridden if you specify shots with run() or in the PUB.
+sampler.options.update(default_shots=1024, dynamical_decoupling={"sequence_type": "XpXm"})
+
+# Print the dictionary format.
+# Server defaults are used for unset options.
+print(asdict(sampler.options))
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+options = Options()
+# This uses auto complete.
+options.resilience_level = 2
+sampler = Sampler(backend=backend, options=options)
+
+# Setting options after primitive initialization.
+# This does bulk update.
+sampler.set_options(shots=2000, optimization_level=0)
+ ```
+
+
+
+
+### Error mitigation and suppression
+
+* Because V2 Sampler returns samples without postprocessing, it does not support resilience levels.
+* V2 Sampler does not currently support `optimization_level`.
+* V2 Estimator does not support resilience level 3. This is because resilience level 3 in V1 Estimator uses Probabilistic Error Cancellation (PEC), which is proven to give unbiased results at the cost of exponential processing time. Level 3 was removed to draw attention to that tradeoff. You can, however, still use PEC as the error mitigation method by specifying the `pec_mitigation` option.
+* V2 Estimator supports `resilience_level` 0-2, as described in the following table. These options are more advanced than their V1 counterparts. You can also explicitly turn on / off individual error mitigation / suppression methods.
+
+ | Level 1 | Level 2 |
+ |---------------------------|---------------------------|
+ | Measurement twirling | Measurement twirling |
+ | Readout error mitigation | Readout error mitigation |
+ | | ZNE |
+
+{/*Verified EstimatorV2. 2/23 */}
+
+
+
+ ```python
+from dataclasses import asdict
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+estimator = Estimator(backend)
+
+# Set resilience_level to 0
+estimator.options. resilience_level = 0
+
+# Turn on measurement error mitigation
+estimator.options.resilience.measure_mitigation = True
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import Estimator, Options
+
+estimator = Estimator(backend, options=options)
+
+options = Options()
+
+options.resilience_level = 2
+```
+
+
+
+{/*Verified 2/28 */}
+
+
+
+ {/*from the boxnote */}
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+sampler = Sampler(backend)
+# Turn on dynamical decoupling with sequence XpXm.
+sampler.options.dynamical_decoupling.enable = True
+sampler.options.dynamical_decoupling.sequence_type = "XpXm"
+
+print(f">> dynamical decoupling sequence to use: {sampler.options.dynamical_decoupling.sequence_type}")
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+options = Options()
+# This uses auto complete.
+options.resilience_level = 2
+sampler = Sampler(backend=backend, options=options)
+
+# Setting options after primitive initialization.
+# This does bulk update.
+sampler.set_options(shots=2000, optimization_level=0)
+ ```
+
+
+
+ ```python
+from qiskit_ibm_runtime import Sampler, Options
+
+sampler = Sampler(backend, options=options)
+
+options = Options()
+
+options.resilience_level = 2
+```
+
+
+
+
+### Transpilation
+
+V2 primitives support only ISA circuits. Because the primitives do not perform layout, routing, and translation operations, the corresponding transpilation options from V1 are not supported. For Estimator, you can still use `optimization_level` to indicate how much optimization the primitives should apply to the ISA circuits. The valid values are 0 and 1.
+
+Dynamical decoupling is no longer automatically added for `optimization_level=1`. You can, however, enable it by using the `dynamical_decoupling` option.
+
+
+### Job status
+
+The V2 primitives have a new `RuntimeJobV2` class, which inherits from `BasePrimitiveJob`. The `status()` method of this new class returns a string instead of JobStatus enum from Qiskit. See the [RuntimeJobV2 API reference](../qiskit-ibm-runtime/qiskit_ibm_runtime.RuntimeJobV2) for details.
+
+
+
+```python
+job = estimator.run(...)
+
+# check if a job is still running
+print(f"Job {job.job_id()} is still running: {job.status() == "RUNNING"}")
+```
+
+
+
+```python
+from qiskit.providers.jobstatus import JobStatus
+
+job = estimator.run(...)
+
+#check if a job is still running
+print(f"Job {job.job_id()} is still running: {job.status() is JobStatus.RUNNING}")
+```
+
+
+
+## Steps to migrate to V2 Estimator
+
+1. Replace `from qiskit_ibm_runtime import Estimator` with `from qiskit_ibm_runtime import EstimatorV2 as Estimator`.
+2. Remove any `from qiskit_ibm_runtime import Options` statements, since the `Options` class is not used by V2 primitives. You can instead pass options as a dictionary when initializing the `Estimator` class (for example `estimator = Estimator(backend, options={“dynamical_decoupling”: {“enable”: True}})`), or set them after initialization:
+ ```python
+ estimator = Estimator(backend)
+ estimator.options.dynamical_decoupling.enable = True
+ ```
+
+3. Review all the [supported options](../qiskit-ibm-runtime/options) and make updates accordingly.
+4. Group each circuit you want to run with the observables and parameter values you want to apply to the circuit in a tuple (a PUB). For example, use `(circuit1, observable1, parameter_set1)` if you want to run `circuit1` with `observable1` and `parameter_set1`.
+
+ 1. You might need to reshape your arrays of observables or parameter sets if you want to apply their outer product. For example, an array of observables of shape (4, 1) and an array of parameter sets of shape (1, 6) will give you a result of (4, 6) expectation values. See the [Numpy broadcasting rules](https://numpy.org/doc/stable/user/basics.broadcasting.html) for more details.
+ 2. You can optionally specify the precision you want for that specific PUB.
+5. Update the estimator `run()` method to pass in the list of PUBs. For example, `run([(circuit1, observable1, parameter_set1)])`.
+ You can optionally specify a `precision` here, which would apply to all PUBs.
+6. V2 Estimator job results are grouped by PUBs. You can see the expectation value and standard error for each PUB by indexing to it. For example:
+ ```python
+ pub_result = job.result()[0]
+ print(f">>> Expectation values: {pub_result.data.evs}")
+ print(f">>> Standard errors: {pub_result.data.stds}")
+ ```
+
+## Estimator full examples
+
+### Run a single experiment
+
+Use Estimator to determine the expectation value of a single circuit-observable pair.
+
+{/*Verified EstimatorV2. 2/23 */}
+
+
+
+ ```python
+import numpy as np
+from qiskit.circuit.library import IQP
+from qiskit.quantum_info import SparsePauliOp, random_hermitian
+from qiskit_ibm_runtime import EstimatorV2 as Estimator, QiskitRuntimeService
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+estimator = Estimator(backend)
+
+n_qubits = 127
+
+mat = np.real(random_hermitian(n_qubits, seed=1234))
+circuit = IQP(mat)
+observable = SparsePauliOp("Z" * n_qubits)
+
+pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
+isa_circuit = pm.run(circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+
+job = estimator.run([(isa_circuit, isa_observable)])
+result = job.result()
+
+print(f" > Expectation value: {result[0].data.evs}")
+print(f" > Metadata: {result[0].metadata}")
+```
+
+
+
+ ```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.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+n_qubits = 127
+
+mat = np.real(random_hermitian(n_qubits, seed=1234))
+circuit = IQP(mat)
+observable = SparsePauliOp("Z" * n_qubits)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+
+estimator = Estimator(backend)
+job = estimator.run(isa_circuit, isa_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.
+
+{/*Verified EstimatorV2. 2/23 */}
+
+
+
+```python
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+
+n_qubits = 3
+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),
+]
+
+isa_circuits = pm.run(circuits)
+isa_observables = [ob.apply_layout(isa_circuits[0].layout) for ob in observables]
+
+
+estimator = Estimator(backend)
+job = estimator.run([(isa_circuits[0], isa_observables[0]),(isa_circuits[1], isa_observables[1]),(isa_circuits[2], isa_observables[2])])
+job_result = job.result()
+for idx in range(len(job_result)):
+ pub_result = job_result[idx]
+ print(f">>> Expectation values for PUB {idx}: {pub_result.data.evs}")
+ print(f">>> Standard errors for PUB {idx}: {pub_result.data.stds}")
+```
+
+
+
+```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.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+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),
+]
+
+# Get ISA circuits
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuits = pm.run(circuits)
+isa_observables = [ob.apply_layout(isa_circuits[0].layout) for ob in observables]
+
+estimator = Estimator(backend)
+job = estimator.run(isa_circuits, isa_observables)
+result = job.result()
+
+print(f" > Expectation values: {result.values}")
+```
+
+
+
+### Run parameterized circuits
+
+{/* This one has been updated from the most recent version of the boxnote. Verified that it works*/}
+
+Use Estimator to run multiple experiments in a single job, leveraging parameter values to increase circuit reusability. In the following example, notice that steps 1 and 2 are the same for V1 and V2.
+
+
+
+ ```python
+import numpy as np
+
+from qiskit.circuit import QuantumCircuit, Parameter
+from qiskit.quantum_info import SparsePauliOp
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService
+
+# Step 1: Map classical inputs to a quantum problem
+
+theta = Parameter("θ")
+
+chsh_circuit = QuantumCircuit(2)
+chsh_circuit.h(0)
+chsh_circuit.cx(0, 1)
+chsh_circuit.ry(theta, 0)
+
+number_of_phases = 21
+phases = np.linspace(0, 2 * np.pi, number_of_phases)
+individual_phases = [[ph] for ph in phases]
+
+ZZ = SparsePauliOp.from_list([("ZZ", 1)])
+ZX = SparsePauliOp.from_list([("ZX", 1)])
+XZ = SparsePauliOp.from_list([("XZ", 1)])
+XX = SparsePauliOp.from_list([("XX", 1)])
+ops = [ZZ, ZX, XZ, XX]
+
+# Step 2: Optimize problem for quantum execution.
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+chsh_isa_circuit = pm.run(chsh_circuit)
+isa_observables = [operator.apply_layout(chsh_isa_circuit.layout) for operator in ops]
+
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+# Step 3: Execute using Qiskit primitives.
+
+# Reshape observable array for broadcasting
+reshaped_ops = np.fromiter(isa_observables, dtype=object)
+reshaped_ops = reshaped_ops.reshape((4, 1))
+
+estimator = Estimator(backend, options={"default_shots": int(1e4)})
+job = estimator.run([(chsh_isa_circuit, reshaped_ops, individual_phases)])
+# Get results for the first (and only) PUB
+pub_result = job.result()[0]
+print(f">>> Expectation values: {pub_result.data.evs}")
+print(f">>> Standard errors: {pub_result.data.stds}")
+print(f">>> Metadata: {pub_result.metadata}")
+```
+
+
+
+ ```python
+import numpy as np
+
+from qiskit.circuit import QuantumCircuit, Parameter
+from qiskit.quantum_info import SparsePauliOp
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService
+
+# Step 1: Map classical inputs to a quantum problem
+
+theta = Parameter("θ")
+
+chsh_circuit = QuantumCircuit(2)
+chsh_circuit.h(0)
+chsh_circuit.cx(0, 1)
+chsh_circuit.ry(theta, 0)
+
+number_of_phases = 21
+phases = np.linspace(0, 2 * np.pi, number_of_phases)
+individual_phases = [[ph] for ph in phases]
+
+ZZ = SparsePauliOp.from_list([("ZZ", 1)])
+ZX = SparsePauliOp.from_list([("ZX", 1)])
+XZ = SparsePauliOp.from_list([("XZ", 1)])
+XX = SparsePauliOp.from_list([("XX", 1)])
+ops = [ZZ, ZX, XZ, XX]
+
+# Step 2: Optimize problem for quantum execution.
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+chsh_isa_circuit = pm.run(chsh_circuit)
+isa_observables = [operator.apply_layout(chsh_isa_circuit.layout) for operator in ops]
+
+from qiskit_ibm_runtime import Estimator
+
+# Step 3: Execute using Qiskit Primitives.
+num_ops = len(isa_observables)
+
+batch_circuits = [chsh_isa_circuit] * number_of_phases * num_ops
+batch_ops = [op for op in isa_observables for _ in individual_phases]
+batch_phases = individual_phases * num_ops
+
+estimator = Estimator(backend, options={"shots": int(1e4)})
+job = estimator.run(batch_circuits, batch_ops, batch_phases)
+expvals = job.result().values
+```
+
+
+
+### Use sessions and advanced options
+
+Explore sessions and advanced options to optimize circuit performance on quantum systems.
+
+{/*Verified EstimatorV2. 2/23 */}
+
+
+
+```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
+from qiskit_ibm_runtime import QiskitRuntimeService, Session, EstimatorV2 as Estimator
+
+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)
+
+pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
+isa_circuit = pm.run(circuit)
+another_isa_circuit = pm.run(another_circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+another_isa_observable = another_observable.apply_layout(another_isa_circuit.layout)
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+with Session(service=service, backend=backend) as session:
+ estimator = Estimator(session=session)
+
+ estimator.options.optimization_level = 1
+ estimator.options.resilience_level = 1
+
+ job = estimator.run([(isa_circuit, isa_observable)])
+ another_job = estimator.run([(another_isa_circuit, another_isa_observable)])
+ result = job.result()
+ another_result = another_job.result()
+
+ # first job
+ print(f" > Expectation value: {result[0].data.evs}")
+ print(f" > Metadata: {result[0].metadata}")
+
+ # second job
+ print(f" > Another Expectation value: {another_result[0].data.evs}")
+ print(f" > More Metadata: {another_result[0].metadata}")
+```
+
+
+
+```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
+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)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+another_isa_circuit = pm.run(another_circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+another_isa_observable = another_observable.apply_layout(another_isa_circuit.layout)
+
+options = Options()
+options.optimization_level = 2
+options.resilience_level = 2
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+with Session(service=service, backend=backend) as session:
+ estimator = Estimator(session=session, options=options)
+ job = estimator.run(isa_circuit, isa_observable)
+ another_job = estimator.run(another_isa_circuit, another_isa_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}")
+```
+
+
+
+## Steps to migrate to V2 Sampler
+
+1. Replace `from qiskit_ibm_runtime import Sampler` with `from qiskit_ibm_runtime import SamplerV2 as Sampler`.
+2. Remove any `from qiskit_ibm_runtime import Options` statements, since the `Options` class is not used by V2 primitives. You can instead pass options as a dictionary when initializing the `Sampler` class (for example `sampler = Sampler(backend, options={“default_shots”: 1024})`), or set them after initialization:
+ ```python
+ sampler = Sampler(backend)
+ sampler.options.default_shots = 1024
+ ```
+3. Review all the [supported options](../api/qiskit-ibm-runtime/options) and make updates accordingly.
+4. Group each circuit you want to run with the observables and parameter values you want to apply to the circuit in a tuple (a PUB). For example, use `(circuit1, parameter_set1)` if you want to run `circuit1` with `parameter_set1`.
+ You can optionally specify the shots you want for that specific PUB.
+5. Update the sampler `run()` method to pass in the list of PUBs. For example, `run([(circuit1, parameter_set1)])`.
+ You can optionally specify `shots` here, which would apply to all PUBs.
+6. V2 Sampler job results are grouped by PUBs. You can see the output data for each PUB by indexing to it. While V2 Sampler returns unweighted samples, the result class has a convenience method to get counts instead. For example:
+ ```python
+ pub_result = job.result()[0]
+ print(f">>> Counts: {pub_result.data.meas.get_counts()}")
+ print(f">>> Per-shot measurement: {pub_result.data.meas.get_counts()}")
+ ```
+
+## Sampler full examples
+
+### Run a single experiment
+
+Use Sampler to determine the counts or quasi-probability distribution of a single circuit.
+
+{/*Verified 2/28 */}
+
+
+```python
+import numpy as np
+from qiskit.circuit.library import IQP
+from qiskit.quantum_info import random_hermitian
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+n_qubits = 127
+
+mat = np.real(random_hermitian(n_qubits, seed=1234))
+circuit = IQP(mat)
+circuit.measure_all()
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+sampler = Sampler(backend)
+job = sampler.run([(isa_circuit,)])
+result = job.result()
+```
+
+
+
+ ```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.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+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 counts or quasi-probability distributions of multiple circuits in one job.
+
+{/*Verified 2/28 */}
+
+
+
+```python
+import numpy as np
+from qiskit.circuit.library import IQP
+from qiskit.quantum_info import random_hermitian
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+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()
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuits = pm.run(circuits)
+pubs = [(qc,) for qc in isa_circuits]
+
+sampler = Sampler(backend)
+job = sampler.run(pubs)
+result = job.result()
+
+for idx, pub_result in enumerate(result):
+ print(f" > Counts for pub {idx}: {pub_result.data.meas.get_counts()}")
+```
+
+
+
+```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.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+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 several experiments in a single job, leveraging parameter values to increase circuit reusability.
+
+{/*Verified 2/28 */}
+
+
+
+```python
+import numpy as np
+from qiskit.circuit.library import RealAmplitudes
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService
+
+# Step 1: Map classical inputs to a quantum problem
+num_qubits = 127
+circuit = RealAmplitudes(num_qubits=num_qubits, 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)
+]
+
+# Step 2: Optimize problem for quantum execution.
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=num_qubits)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+# Step 3: Execute using Qiskit primitives.
+
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
+sampler = Sampler(backend)
+job = sampler.run([(isa_circuit, parameter_values)])
+result = job.result()
+# Get results for the first (and only) PUB
+pub_result = result[0]
+# Get counts from the classical register "meas".
+print(f" >> Counts for the meas output register: {pub_result.data.meas.get_counts()}")
+```
+
+
+
+```python
+import numpy as np
+from qiskit.circuit.library import RealAmplitudes
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService
+
+# Step 1: Map classical inputs to a quantum problem
+num_qubits = 5
+circuit = RealAmplitudes(num_qubits=num_qubits, 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)
+]
+
+# Step 2: Optimize problem for quantum execution.
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=num_qubits)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+# Step 3: Execute using Qiskit primitives.
+
+from qiskit_ibm_runtime import Sampler
+
+sampler = Sampler(backend)
+job = sampler.run([isa_circuit] * 3, parameter_values)
+result = job.result()
+
+print(f" > Quasi-probability distribution: {result.quasi_dists}")
+print(f" > Metadata: {result.metadata}")
+```
+
+
+
+### Use sessions and advanced options
+
+Explore sessions and advanced options to optimize circuit performance on quantum systems.
+
+{/*Verified 2/28 */}
+
+
+
+```python
+import numpy as np
+from qiskit.circuit.library import IQP
+from qiskit.quantum_info import random_hermitian
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler, Session
+
+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()
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+another_isa_circuit = pm.run(another_circuit)
+
+service = QiskitRuntimeService()
+
+# Turn on dynamical decoupling with sequence XpXm.
+sampler.options.dynamical_decoupling.enable = True
+sampler.options.dynamical_decoupling.sequence_type = "XpXm"
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+with Session(service=service, backend=backend) as session:
+ sampler = Sampler(session=session)
+ job = sampler.run([(isa_circuit)])
+ another_job = sampler.run([(another_isa_circuit)])
+ result = job.result()
+ another_result = another_job.result()
+
+# first job
+print(f" > Counts for job 1: {result[0].data.meas.get_counts()}")
+
+# second job
+print(f" > Counts for job 2: {another_result[0].data.meas.get_counts()}")
+```
+
+
+
+```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.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+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}")
+```
+
+
\ No newline at end of file
diff --git a/docs/build/bit-ordering.mdx b/docs/build/bit-ordering.mdx
index 4305d0f5da1..9faa9ebe527 100644
--- a/docs/build/bit-ordering.mdx
+++ b/docs/build/bit-ordering.mdx
@@ -57,11 +57,27 @@ the value $2^\text{label}$ (label being the qubit's index in
with bit $0$ being `0`, and bit $1$ being `1`. This is interpreted as the
decimal integer `2` (measured with probability `1.0`).
-```python
+
+
+ ```python
+from qiskit.primitives import Samplerv2 as Sampler
+qc.measure_all()
+
+job = sampler.run([(qc)])
+result = job.result()
+print(f" > Counts: {result[0].data.meas.get_counts()}")
+```
+
+
+
+ ```python
from qiskit.primitives import Sampler
qc.measure_all()
+
Sampler().run(qc).result().quasi_dists[0]
```
+
+
```
{2: 1.0}
diff --git a/docs/build/circuit-construction.ipynb b/docs/build/circuit-construction.ipynb
index 368af1e3735..57b67262648 100644
--- a/docs/build/circuit-construction.ipynb
+++ b/docs/build/circuit-construction.ipynb
@@ -372,7 +372,7 @@
"qc.rx(angle, 0)\n",
"\n",
"from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
- "qc = generate_preset_pass_manager(3, basis_gates=['u', 'cx']).run(qc)\n",
+ "qc = generate_preset_pass_manager(optimization_level=3, basis_gates=['u', 'cx']).run(qc)\n",
"\n",
"qc.draw(\"mpl\")"
]
diff --git a/docs/run/advanced-runtime-options.mdx b/docs/run/advanced-runtime-options.mdx
index bf2ae6be88e..46cada9fef3 100644
--- a/docs/run/advanced-runtime-options.mdx
+++ b/docs/run/advanced-runtime-options.mdx
@@ -6,20 +6,26 @@ 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:
+When calling the primitives, you can pass in options by using an options class or a dictionary. In the options classes, commonly used options, such as `resilience_level`, are at the first level. Other options are grouped into different categories, such as `execution`. See all the available options in the [API reference](../api/qiskit-ibm-runtime/options).
-To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations; consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `options.transpilation.skip_transpilation`.
+To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `optimization_level=0`.
-
-
- 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
+ This section focuses on Qiskit Runtime primitive options. 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.
-## Instantiate the Options class
+## V2 changes
+Options are specified differently in the V2 primitives in these ways:
+
+- `SamplerV2` and `EstimatorV2` now have separate options classes. You can see the available options and update option values during or after primitive initialization.
+- Instead of the `set_options()` method, V2 primitive options have the `update()` method that applies changes to the `options` attribute.
+- If you do not specify a value for an option, it is given a special value of `Unset` and the server defaults are used.
+- For V2 primitives, the `options` attribute is the `dataclass` Python type. You can use the built-in `asdict` method to convert it to a dictionary.
+
+## Instantiate the Options class (V1)
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.
@@ -40,36 +46,122 @@ options.execution.shots = 2048
```
## Pass options to a primitive
-### Options class
+### Options class
+
+When creating an instance of the `Estimator` or `Sampler` class, you can pass in the `options` you created in the options class. Those options will then be applied when you use `run()` to perform the calculation. Example:
+
+
+
+ `SamplerV2` and `EstimatorV2` have separate options classes that do not need to be instantiated. You can see the available options and update option values during or after primitive initialization. Those options will then be applied when you use `run()` to perform the calculation. Example:
+
+```python
+estimator = Estimator(backend=backend)
-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:
+# Setting options after primitive initialization
+# This uses auto complete.
+estimator.options.optimization_level = 1
+estimator.options.default_shots = 4000
+```
+
+
+When creating an instance of the `Estimator` or `Sampler` class, you can pass in the `options` you created in the options class. 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]}")
```
+
+
+
+### Primitive initialization
+
+You can specify options when initializing the primitive.
+
+
+
+
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+estimator = Estimator(backend, options={"resilience_level": 2})
+```
+
+
+
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+estimator = Estimator(backend, options={"resilience_level": 2})
+```
+
+
+
### 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).
+
+
+In V2, the only options you can pass to `run()` are options defined in the interface. That is, `shots` for Sampler and `precision` for Estimator.
+```python
+# Sample two circuits at 128 shots each.
+sampler.run([(circuit1,), (circuit2,)], shots=128)
+```
+
+
+
+You can pass any options to `run()`. 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. There are several ways to set and update shots with the primitives.
+
+
+
+ ```python
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
+# Setting shots during primitive initialization
+sampler = Sampler(backend, options={"default_shots": 4096})
+# Setting options after primitive initialization
+# This uses auto complete.
+sampler.options.default_shots=2000
+
+# This does bulk update. The value for default_shots is overridden if you specify shots with run() or in the PUB.
+sampler.options.update(default_shots=1024, dynamical_decoupling={"sequence_type": "XpXm"})
+
+# Sample two circuits at 128 shots each.
+sampler.run([(circuit1,), (circuit2,)], shots=128)
+```
+
-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
+
+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
@@ -98,6 +190,10 @@ 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
@@ -109,7 +205,24 @@ The Qiskit Runtime primitives may perform additional runtime compilation to opti
See the Optimization level table in the
[Runtime compilation topic](configure-runtime-compilation#set-the-optimization-level) for further details.
-
+
+
+ The optimization level option is a "first-level option". Sampler V2 does not currently support `optimization_level`.
+
+```python
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+estimator = Estimator(session=backend, options={"optimization_level": 1})
+
+# or..
+estimator.options.optimization_level = 1
+```
+
+To turn off all optional runtime compilation steps, you must set `optimization_level=0`. V2 primitives do not support any advanced transpilation options.
+
+
+
+
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.
@@ -140,15 +253,33 @@ 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
+algorithm. These methods can be set through the `resilience_level` option. For more information about error mitigation, see the
[Configure error mitigation topic](configure-error-mitigation).
+
+
+With V2 Estimator, you can set resilience levels 0-2 and you can also turn on and off various error mitigation settings for fine tuning.
+
+```python
+estimator = Estimator(backend=backend)
+
+estimator.options.resilience_level = 2
+estimator.options.zne_mitigation = True
+estimator.options.zne.noise_factors = [1, 3, 5]
+```
+
+
+
+The method selected for each level is
+different for `Sampler` and `Estimator`.
+
The configuration is similar to the other options:
```python
@@ -163,6 +294,10 @@ options.resilience_level = 2
estimator = Estimator(session=backend, options=options)
```
+
+
+
+
## Next steps
diff --git a/docs/run/configure-error-mitigation.mdx b/docs/run/configure-error-mitigation.mdx
index e35e7fe2e58..5d204689090 100644
--- a/docs/run/configure-error-mitigation.mdx
+++ b/docs/run/configure-error-mitigation.mdx
@@ -15,6 +15,8 @@ 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.
+Sampler V2 does not support specifying resilience levels. However, you can turn on or off individual error mitigation / suppression methods. See the [Custom error settings](#advanced-options) section for details.
+
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
@@ -39,16 +41,36 @@ expectation values.
-To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations; consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `options.transpilation.skip_transpilation`.
+To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `optimization_level=0`.
+
+
+
+
+ In V2, Estimator supports the following resilience levels. Sampler does not support resilience levels.
+
+| Resilience Level | Definition | Technique |
+|------------------|-------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
+| 0 | No mitigation | None |
+| 1 [Default] | Minimal mitigation costs: Mitigate error associated with readout errors | Twirled Readout Error eXtinction (TREX) measurement twirling |
+| 2 | Medium mitigation costs. Typically reduces bias in estimators, but is not guaranteed to be zero-bias. | Level 1 + Zero Noise Extrapolation (ZNE) and gate twirling
+
+
+
+
+ Resilience levels in V1 primitives:
| 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) | - |
+| 3 | Heavy mitigation with layer sampling. Theoretically expected to deliver zero-bias estimators. | Probabilistic Error Cancellation (PEC) | - |
+
+
+
+
@@ -69,7 +91,84 @@ applied at each resilience level.
runtime warning. For more information visit the [Q-CTRL documentation](https://docs.q-ctrl.com/q-ctrl-embedded).
-## Configure the Estimator with resilience levels
+## Configure Estimator V2 with resilience levels
+
+You can use resilience levels to specify error mitigation techniques, or you can set custom techniques individually as described in [Custom error settings with Estimator V2.](#advanced-options) You cannot specify resilience levels in Sampler V2. However, you can set custom techniques individually.
+
+
+Resilience Level 0
+
+No error mitigation is applied to the user program.
+
+
+
+
+
+
+Resilience Level 1
+
+Level 1 applies **readout error mitigation** and **measurement twirling** by applying 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. 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).
+
+
+
+
+
+Resilience Level 2
+
+Level 2 applies the **error mitigation techniques included in level 1** and also applies **gate twirling** and uses the **Zero Noise Extrapolation method (ZNE)**. ZNE 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.
+
+
+
+
+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.
+
+In Level 2, the TREX method randomly flips qubits through X gates immediately before measurement,
+and flips the corresponding measured bit if an X gate was applied. This approach is described further in [Model-free
+readout-error mitigation for quantum expectation
+values](https://arxiv.org/abs/2012.09738).
+
+
+
+### 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
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+# Setting options during primitive initialization
+estimator = Estimator(backend, options={"resilience_level": 2})
+```
+
+
+
+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.
+
+
+## Configure Estimator (V1) with resilience levels
@@ -111,7 +210,7 @@ stage). This approach tends to reduce errors in expectation values, but
is not guaranteed to produce an unbiased result.
-
+
The overhead of this method scales with the number of noise factors. The
default settings sample the expectation value at three noise factors,
@@ -212,12 +311,12 @@ problems.
-## Example
+### 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`.
+setting `resilience_level=2`.
```python
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options
@@ -225,12 +324,10 @@ 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")
+options.optimization_level = 1
+backend = service.least_busy(operational=True, simulator=False)
estimator = Estimator(options=options, backend=backend)
-job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1])
-psi1_H1 = job.result()
```
@@ -238,9 +335,11 @@ psi1_H1 = job.result()
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.
-## Configure Sampler with resilience levels
+## Configure Sampler (V1) with resilience levels
+
+Sampler V2 does not support specifying resilience levels. However, you can turn on or off individual error mitigation / suppression methods. See [Custom error settings](#advanced-error) for details.
-The Sampler default resilience setting (level 1) enables readout error
+The Sampler V1 default resilience setting (level 1) enables readout error
mitigation to allow users to generate mitigated quasi-probability
distributions.
@@ -265,13 +364,58 @@ 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")
+options.optimization_level = 1
+backend = service.least_busy(operational=True, simulator=False)
sampler = Sampler(backend, options=options)
```
-## Advanced resilience options
+
+## Custom error settings
+
+With Estimator V2, you can turn on and off individual error mitigation and suppression methods, including dynamical decoupling, gate and measurement twirling, measurement error mitigation, and ZNE.
+
+
+## Custom error settings (V2 primitives)
+With the V2 primitives, you can turn on and off individual error mitigation and suppression methods. See the [API reference](/api/qiskit-ibm-runtime/options) for the list of available options.
+
+
+
+ ```python
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+estimator = Estimator(backend)
+options = estimator.options
+# Turn on gate twirling.
+options.twirling.enable_gates = True
+# Turn on measurement error mitigation.
+options.resilience.measure_mitigation = True
+
+print(f">>> gate twirling is turned on: {estimator.options.twirling.enable_gates}")
+print(f">>> measurement error mitigation is turned on: {estimator.options.resilience.measure_mitigation}")
+```
+
+
+
+```python
+from qiskit_ibm_runtime import SamplerV2 as Sampler, Options
+
+# Estimator and Sampler now have different options
+options = sampler.options
+
+options.dynamical_decoupling.enable = True
+
+print(f">>> dynamical decoupling is turned on: {sampler.options.dynamical_decoupling.enable}")
+```
+
+
+
+
+## Advanced resilience options (V1 primitives)
You can tune advanced options to configure your resilience strategy
further. These methods can be used alongside resilience levels where you
@@ -290,8 +434,8 @@ add options to tune other resilience levels that include PEC.
| | `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. |
+| `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. |
diff --git a/docs/run/configure-runtime-compilation.mdx b/docs/run/configure-runtime-compilation.mdx
index bca59f8a4b0..1625d3f1abd 100644
--- a/docs/run/configure-runtime-compilation.mdx
+++ b/docs/run/configure-runtime-compilation.mdx
@@ -10,18 +10,18 @@ Runtime compilation techniques optimize and transform your circuit to minimize e
Primitives let you employ runtime compilation by setting the optimization level (`optimization_level` option) and by choosing advanced runtime compilation options.
-
-To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations; consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `options.transpilation.skip_transpilation`.
-
-
+V2 primitives support optimization levels 0 and 1 only.
+
+To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `optimization_level=0`.
+
## 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.
- In current primitive versions, optimization levels 2 and 3 behave identically to level 1.
+ In primitive version 1, optimization levels 2 and 3 behave identically to level 1. V2 primitives do not accept levels higher than 1.
@@ -47,9 +47,10 @@ The `optimization_level` setting specifies how much optimization to perform on t
1, 2, 3
Light optimization:
+
- Single-qubit gate optimization
- Two-qubit gate optimization
- - Error suppression: dynamical decoupling
+ - Error suppression: dynamical decoupling (V1 primitives only. For V2 primitives, you can enable it by using the `dynamical_decoupling` option.)
@@ -67,6 +68,36 @@ The `optimization_level` setting specifies how much optimization to perform on t
### Example: configure Estimator with optimization levels
+
+
+```python
+from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit.circuit.library import RealAmplitudes
+from qiskit.quantum_info import SparsePauliOp
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+psi = RealAmplitudes(num_qubits=2, reps=2)
+H = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
+theta = [0, 1, 1, 2, 3, 5]
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+psi = pm.run(psi)
+H = H.apply_layout(psi.layout)
+
+estimator = Estimator(backend=backend)
+
+estimator.options.optimization_level = 1
+
+job = estimator.run([(psi, H, theta)])
+
+psi1_H1 = job.result()[0]
+ ```
+
+
+
```python
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
@@ -91,26 +122,43 @@ job = estimator.run(circuits=[psi], observables=[H], parameter_values=[theta])
psi1_H1 = job.result()
```
+
+
+
+
If the optimization level is not specified, the service uses `optimization_level = 1`.
-### Example: configure Sampler with optimization levels
+
+## Advanced runtime compilation options
+
+
+ In the V2 primitives, you can explicitly enable and disable individual error mitigation/suppression methods, such as dynamical decoupling.
```python
-from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Options
+
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime import SamplerV2 as Sampler
service = QiskitRuntimeService()
-backend = service.backend("ibmq_qasm_simulator")
-options = Options(optimization_level=1)
+backend = service.least_busy(operational=True, simulator=False)
-sampler = Sampler(options=options, backend=backend)
-```
+sampler = Sampler(backend)
-
-## Advanced runtime compilation options
+# Turn on dynamical decoupling with sequence XpXm.
+sampler.options.dynamical_decoupling.enable = True
+sampler.options.dynamical_decoupling.sequence_type = "XpXm"
+
+print(f">>> dynamical decoupling sequence to use: {sampler.options.dynamical_decoupling.sequence_type}")
+```
+
+
+
+ Because all input must be ISA, options.transpilation.xxx will be ignored.
+
+
-Future versions of the primitives will offer options to tune runtime compilation. Currently, the only option with any effect is `skip_transpilation` (bool), which turns off all optimizations done with the primitives.
## Next steps
diff --git a/docs/run/estimate-job-run-time.mdx b/docs/run/estimate-job-run-time.mdx
index 75151cbdca2..b705b804fbd 100644
--- a/docs/run/estimate-job-run-time.mdx
+++ b/docs/run/estimate-job-run-time.mdx
@@ -21,7 +21,48 @@ To ensure faster and more efficient results, as of 1 March 2024, circuits and ob
Example:
-```python
+
+
+ ```python
+from qiskit import QuantumCircuit
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+
+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)
+
+# Generate ISA circuits
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(qc)
+
+# Create a Sampler object
+sampler = Sampler(backend)
+
+# Submit the circuit to the sampler
+job = sampler.run([(isa_circuit,)])
+
+print(job.usage_estimation)
+```
+
+
+
+ ```python
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
@@ -57,6 +98,8 @@ job = sampler.run(isa_circuit)
print(job.usage_estimation)
```
+
+
Output:
diff --git a/docs/run/instances.mdx b/docs/run/instances.mdx
index 2272c0b0f73..ddd0956c62a 100644
--- a/docs/run/instances.mdx
+++ b/docs/run/instances.mdx
@@ -54,7 +54,28 @@ You can specify an instance when initializing the service or provider, or when c
### qiskit-ibm-runtime
-```python
+
+
+ ```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 = SamplerV2(backend=backend1) # this will use hub1/group1/project1
+sampler2 = SamplerV2(backend=backend2) # this will use hub2/group2/project2
+```
+
+
+
+ ```python
# Optional: List all the instances you can access.
service = QiskitRuntimeService(channel='ibm_quantum')
@@ -70,6 +91,8 @@ 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
diff --git a/docs/run/primitives-examples.mdx b/docs/run/primitives-examples.mdx
index d528a78ed31..fd06a703d8a 100644
--- a/docs/run/primitives-examples.mdx
+++ b/docs/run/primitives-examples.mdx
@@ -9,7 +9,7 @@ description: Practical examples of using primitives in Qiskit Runtime.
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)
-To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations; consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `options.transpilation.skip_transpilation`.
+To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `optimization_level=0`.
@@ -24,6 +24,39 @@ Efficiently calculate and interpret expectation values of the quantum operators
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.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit.quantum_info import SparsePauliOp, random_hermitian
+from qiskit_ibm_runtime import EstimatorV2 as Estimator, QiskitRuntimeService
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+estimator = Estimator(backend)
+
+n_qubits = 127
+
+mat = np.real(random_hermitian(n_qubits, seed=1234))
+circuit = IQP(mat)
+observable = SparsePauliOp("Z" * n_qubits)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+
+job = estimator.run([(isa_circuit, isa_observable)])
+result = job.result()
+
+print(f" > Expectation value: {result[0].data.evs}")
+print(f" > Metadata: {result[0].metadata}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -33,7 +66,7 @@ from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
n_qubits = 127
@@ -53,11 +86,59 @@ 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.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit.circuit.library import IQP
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit.quantum_info import SparsePauliOp, random_hermitian
+from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+
+n_qubits = 127
+rng = np.random.default_rng()
+mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]
+
+pubs = []
+circuits = [IQP(mat) for mat in mats]
+observables = [
+ SparsePauliOp("X" * n_qubits),
+ SparsePauliOp("Y" * n_qubits),
+ SparsePauliOp("Z" * n_qubits),
+]
+
+# Get ISA circuits
+
+for qc, obs in zip(circuits, observables):
+ isa_circuit = pm.run(qc)
+ isa_obs = obs.apply_layout(isa_circuit.layout)
+ pubs.append((isa_circuit, isa_obs))
+
+estimator = Estimator(backend)
+job = estimator.run(pubs)
+job_result = job.result()
+
+for idx in range(len(pubs)):
+ pub_result = job_result[idx]
+ print(f">>> Expectation values for PUB {idx}: {pub_result.data.evs}")
+ print(f">>> Standard errors for PUB {idx}: {pub_result.data.stds}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -68,7 +149,7 @@ from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
n_qubits = 127
@@ -91,11 +172,70 @@ 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 import QuantumCircuit, Parameter
+from qiskit.quantum_info import SparsePauliOp
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService
+
+# Step 1: Map classical inputs to a quantum problem
+
+theta = Parameter("θ")
+
+chsh_circuit = QuantumCircuit(2)
+chsh_circuit.h(0)
+chsh_circuit.cx(0, 1)
+chsh_circuit.ry(theta, 0)
+
+number_of_phases = 21
+phases = np.linspace(0, 2 * np.pi, number_of_phases)
+individual_phases = [[ph] for ph in phases]
+
+ZZ = SparsePauliOp.from_list([("ZZ", 1)])
+ZX = SparsePauliOp.from_list([("ZX", 1)])
+XZ = SparsePauliOp.from_list([("XZ", 1)])
+XX = SparsePauliOp.from_list([("XX", 1)])
+ops = [ZZ, ZX, XZ, XX]
+
+# Step 2: Optimize problem for quantum execution.
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+chsh_isa_circuit = pm.run(chsh_circuit)
+isa_observables = [operator.apply_layout(chsh_isa_circuit.layout) for operator in ops]
+
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+# Step 3: Execute using Qiskit primitives.
+
+# Reshape observable array for broadcasting
+reshaped_ops = np.fromiter(isa_observables, dtype=object)
+reshaped_ops = reshaped_ops.reshape((4, 1))
+
+estimator = Estimator(backend, options={"default_shots": int(1e4)})
+job = estimator.run([(chsh_isa_circuit, reshaped_ops, individual_phases)])
+# Get results for the first (and only) PUB
+pub_result = job.result()[0]
+print(f">>> Expectation values: {pub_result.data.evs}")
+print(f">>> Standard errors: {pub_result.data.stds}")
+print(f">>> Metadta: {pub_result.metadata}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import RealAmplitudes
@@ -105,7 +245,7 @@ from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
circuit = RealAmplitudes(num_qubits=127, reps=2)
# Define three sets of parameters for the circuit
@@ -125,10 +265,64 @@ 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.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit.quantum_info import SparsePauliOp, random_hermitian
+from qiskit_ibm_runtime import QiskitRuntimeService, Session, EstimatorV2 as Estimator
+
+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)
+
+pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
+isa_circuit = pm.run(circuit)
+another_isa_circuit = pm.run(another_circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+another_isa_observable = another_observable.apply_layout(another_isa_circuit.layout)
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+with Session(service=service, backend=backend) as session:
+ estimator = Estimator(session=session)
+
+ estimator.options.optimization_level = 1
+ estimator.options.resilience_level = 1
+
+ job = estimator.run([(isa_circuit, isa_observable)])
+ another_job = estimator.run([(another_isa_circuit, another_isa_observable)])
+ result = job.result()
+ another_result = another_job.result()
+
+ # first job
+ print(f" > Expectation value: {result[0].data.evs}")
+ print(f" > Metadata: {result[0].metadata}")
+
+ # second job
+ print(f" > Another Expectation value: {another_result[0].data.evs}")
+ print(f" > More Metadata: {another_result[0].metadata}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -158,7 +352,7 @@ options.resilience_level = 2
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
@@ -173,6 +367,8 @@ print(f" > Expectation values job 1: {result.values}")
# second job
print(f" > Expectation values job 2: {another_result.values}")
```
+
+
## Sampler examples
@@ -180,8 +376,37 @@ Generate entire error-mitigated quasi-probability distributions sampled from qua
### Run a single experiment
-Use Sampler to determine the quasi-probability distribution of a single circuit.
+Use Sampler to return the measurement outcome as a quasi-probability distribution (V1) or as **bitstrings** or
+ **counts** (V2) 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, SamplerV2 as Sampler
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+n_qubits = 127
+
+mat = np.real(random_hermitian(n_qubits, seed=1234))
+circuit = IQP(mat)
+circuit.measure_all()
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+sampler = Sampler(backend)
+job = sampler.run([(isa_circuit,)])
+result = job.result()
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -191,7 +416,7 @@ from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
n_qubits = 127
@@ -209,11 +434,47 @@ 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.
+Use Sampler to return the measurement outcome as a quasi-probability distribution (V1) or as **bitstrings** or
+ **counts** (V2) of multiple circuits in one job.
+
+
+
+```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
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+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()
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuits = pm.run(circuit)
+
+sampler = Sampler(backend)
+job = sampler.run([(isa_circuits)])
+result = job.result()
+
+print(f" > Counts: {result[0].data.meas.get_counts()}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -223,7 +484,7 @@ from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
n_qubits = 127
@@ -242,11 +503,57 @@ 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.
+Run several 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.transpiler.preset_passmanagers import generate_preset_pass_manager
+from qiskit_ibm_runtime import QiskitRuntimeService
+
+# Step 1: Map classical inputs to a quantum problem
+num_qubits = 127
+circuit = RealAmplitudes(num_qubits=num_qubits, 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)
+]
+
+# Step 2: Optimize problem for quantum execution.
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=num_qubits)
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+# Step 3: Execute using Qiskit primitives.
+
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
+sampler = Sampler(backend)
+job = sampler.run([(isa_circuit, parameter_values)])
+result = job.result()
+# Get results for the first (and only) PUB
+pub_result = result[0]
+# Get counts from the classical register "meas".
+print(f" >> Counts for the meas output register: {pub_result.data.meas.get_counts()}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import RealAmplitudes
@@ -255,7 +562,7 @@ from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
circuit = RealAmplitudes(num_qubits=127, reps=2)
circuit.measure_all()
@@ -275,11 +582,56 @@ 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, SamplerV2 as Sampler, Session
+
+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()
+
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+another_isa_circuit = pm.run(another_circuit)
+
+service = QiskitRuntimeService()
+
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
+
+with Session(service=service, backend=backend) as session:
+ sampler = Sampler(session=session)
+ job = sampler.run([(isa_circuit)])
+ another_job = sampler.run([(another_isa_circuit)])
+ result = job.result()
+ another_result = another_job.result()
+
+# first job
+print(f" > Counts for job 1: {result[0].data.meas.get_counts()}")
+
+# second job
+print(f" > Counts for job 2: {another_result[0].data.meas.get_counts()}")
+```
+
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -307,7 +659,7 @@ options.resilience_level = 0
service = QiskitRuntimeService()
-backend = service.get_backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
with Session(service=service, backend=backend) as session:
sampler = Sampler(session=session, options=options)
@@ -322,10 +674,14 @@ 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
+ - Read [Migrate to V2 primitives](/api/migration-guides/v2-primitives).
- [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.
- Learn how to transpile locally in the [Transpile](../transpile/) section.
diff --git a/docs/run/primitives-get-started.mdx b/docs/run/primitives-get-started.mdx
index 4303f088454..667eb7abb37 100644
--- a/docs/run/primitives-get-started.mdx
+++ b/docs/run/primitives-get-started.mdx
@@ -19,9 +19,11 @@ To ensure faster and more efficient results, as of 1 March 2024, circuits and ob
## Get started with Estimator
+{/*Verified the v2 examples 2/29 */}
+
### 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.
+Because Qiskit Runtime `Estimator` is a managed service, you 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.
@@ -29,13 +31,15 @@ Follow the steps in the [Install and set up topic](../start/install) if you don'
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
-backend = service.backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
```
### 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.
+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
@@ -49,32 +53,90 @@ circuit = IQP(mat)
observable = SparsePauliOp("Z" * n_qubits)
print(f">>> Observable: {observable.paulis}")
```
-
-The circuit and observable need to be transformed to only use instructions supported by the system. We'll use the transpiler to do this.
+ The circuit and observable need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits). We'll use the transpiler to do this.
```python
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
```
+
+
+
+```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}")
+```
+ The circuit and observable need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits). We'll use the transpiler to do this.
+
+```python
+pm = generate_preset_pass_manager(backend=backend)
+isa_circuit = pm.run(circuit)
+isa_observable = observable.apply_layout(isa_circuit.layout)
+```
+
+
+
+### 3. Initialize Qiskit Runtime Estimator
+
+We want to use the Qiskit Runtime `Estimator`, so we initialize an instance of `qiskit_ibm_runtime.Estimator` instead of `qiskit.primitives.Estimator`.
-### 3. Initialize the Qiskit Runtime Estimator
+When you initialize the `Estimator`, you must pass in the system or simulator you previously selected as the target. You could also do this within the `session` parameter.
-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.
+
+
+ When using V2 Estimator, for backward compatibility, you must explicitly import EstimatorV2. After V1 support ends, you can use either `import` command (`from qiskit_ibm_runtime import Estimator` or `from qiskit_ibm_runtime import EstimatorV2`) to import EstimatorV2.
+
+```python
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
+
+estimator = Estimator(backend=backend)
+ ```
+
+
```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.
+Next, invoke the `run()` method to calculate expectation values for the input circuits and observables.
+
+
+For V2 Estimator, the circuit, observable, and optional paramater 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()}")
+```
+
+```python
+result = job.result()
+print(f">>> {result}")
+print(f" > Expectation value: {result[0].data.evs}")
+print(f" > Metadata: {result[0].metadata}")
+```
+
+
+
+ ```python
job = estimator.run(isa_circuit, isa_observable)
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
@@ -86,13 +148,15 @@ print(f">>> {result}")
print(f" > Expectation value: {result.values[0]}")
print(f" > Metadata: {result.metadata[0]}")
```
+
+
## 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.
+Because Qiskit Runtime `Sampler` is a managed service, you 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.
@@ -100,13 +164,15 @@ Follow the steps in the [Install and set up topic](../start/install) if you don'
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
-backend = service.backend("ibm_brisbane")
+backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
```
### 2. Create a circuit
-Just like the section before, you will need at least one circuit as the input to the `Sampler` primitive.
+You need at least one circuit as the input to the `Sampler` primitive.
+
+
```python
import numpy as np
from qiskit.circuit.library import IQP
@@ -126,24 +192,80 @@ Again, we use the transpiler to get an ISA circuit.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
```
+
-### 3. Initialize the Qiskit Runtime Sampler
+
+ ```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
-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`.
+n_qubits = 127
-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.
+mat = np.real(random_hermitian(n_qubits, seed=1234))
+circuit = IQP(mat)
+circuit.measure_all()
+```
+Again, we use the transpiler to get an ISA circuit.
```python
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+```
+
+
+
+### 3. Initialize the Qiskit Runtime Sampler
+
+Here we initialize an instance of `qiskit_ibm_runtime.Sampler` instead of `qiskit.primitives.Sampler` to use the Qiskit Runtime `Sampler`.
+
+When you initialize the `Sampler`, you need to pass in the simulator or system you previously selected as the target. You could also do this within the `session` parameter.
+
+
+
+ ```python
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
+sampler = Sampler(backend=backend)
+```
+
+
+
+ ```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.
+Next, invoke the `run()` method to generate the output.
+
+
+
+For V2 Sampler, the circuit and optional paramater 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()}")
+```
+
+```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()}")
+```
+
+
+
+ ```python
job = sampler.run(isa_circuit)
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
@@ -154,10 +276,13 @@ print(f">>> {result}")
print(f" > Quasi-probability distribution: {result.quasi_dists[0]}")
print(f" > Metadata: {result.metadata[0]}")
```
+
+
## Next steps
- Review detailed [primitives examples.](primitives-examples)
+ - Read [Migrate to V2 primitives](/api/migration-guides/v2-primitives).
- 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.
diff --git a/docs/run/primitives.mdx b/docs/run/primitives.mdx
index 6bf33f20db3..eae9c5cab60 100644
--- a/docs/run/primitives.mdx
+++ b/docs/run/primitives.mdx
@@ -6,14 +6,14 @@ description: Introduction to primitives in Qiskit and Qiskit Runtime, and an exp
# Introduction to primitives
-Computing systems are built upon multiple layers of abstraction. Abstractions allow us to focus on a
+Computing systems are built on multiple layers of abstraction. Abstractions allow 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 need (for example, you might
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 use a programming library 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
+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.
@@ -21,7 +21,7 @@ As we move toward larger systems and more complex workflows, the focus shifts fr
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*.
+These tasks motivated the design of the 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
@@ -32,17 +32,17 @@ you are trying to achieve.
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 Qiskit Runtime enable access to appropriate systems through native implementations of
+Providers like Qiskit Runtime enable access to appropriate systems through native implementations of
their own primitives.
-To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations; consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `options.transpilation.skip_transpilation`.
+To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `optimization_level=0`.
## 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
+For Qiskit users, primitives let you write quantum code for a specific system without having to explicitly
+manage every detail. In addition, because of the additional layer of abstraction, you might 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.
@@ -51,21 +51,112 @@ For hardware providers, implementing primitives natively means you can provide y
way to access your hardware features. It is therefore easier for your users to benefit from your hardware's
best capabilities.
+## V2 primitives
+
+Version 2 is first the major interface change since the introduction of Qiskit Runtime primitives. Based on user feedback, the new version introduces the following major changes:
+
+* The **new interface** lets you specify a single circuit and multiple observables (if using Estimator) and parameter value sets for that circuit.
+* You can **turn on or off individual error mitigation and suppression methods**.
+* You can choose to **get counts or per-shot measurements** instead of quasi-probabilities from V2 Sampler.
+* Due to scaling issues, V2 Sampler does not support specifying a resilience level, and V2 Estimator supports only levels 0 - 2.
+* To reduce the total execution time, v2 primitives only support ISA circuits. You can use the [Qiskit transpiler](advanced-runtime-options#runtime-compilation) (manually) or the [AI-driven transpilation service (premium users)](../transpile/qiskit-transpiler-service) to transform the circuits before making the queries to the primitives.
+
+### Interface changes
+
+The updated interface uses a *primitive unified bloc* (PUB) for input. Each PUB is a tuple that contains a circuit and the data broadcasted to it. This greatly simplifies your ability to send complex data to a circuit. Previously, you had to specify the same circuit multiple times to match the size of the data to be combined. A summary of the changes to each primitive follows.
+
+#### Estimator V1
+
+* Takes three parameters: circuits, observables, and parameter values.
+* Each parameter can be a single value or a list.
+* The length of the parameters must match.
+* Elements from each are aggregated.
+
+Example:
+
+```python
+estimator.run([circuit1, circuit2, ...],[observable1, observable2, ...],[param_values1, param_values2, ...] )
+```
+
+#### Estimator V2
+
+* Takes one parameter: PUBs in the format (``, ``, ``, ``)
+* Numpy [broadcasting rules](https://numpy.org/doc/stable/user/basics.broadcasting.html) are used when combining observables and parameter values.
+* Each input PUB has a corresponding PubResult that contains both data and metadata.
+
+Example:
+
+```python
+estimator.run([(circuit1, observable1, param_values1),(circuit2, observable2, param_values2) ])
+```
+
+#### Sampler V1
+
+* Takes two parameters: circuits and parameter values.
+* Each parameter can be a single value or a list.
+* The length of the parameters must match.
+* Elements from each are aggregated.
+
+Example:
+
+```python
+sampler.run([circuit1, circuit2, ...],[observable1, observable2, ...],[param_values1, param_values2, ...] )
+```
+
+#### Sampler V2
+
+* Takes one parameter: PUBs in the format (``, ``, ``)
+* Elements from each are aggregated.
+* Obeys program outputs. Typically this is a bit array but can also be an array of complex numbers (measurement level 1).
+* Returns raw data type. Data from each shot is returned (analogous to `memory=True` in the `backend.run` interface), and post-processing is done by using convenience methods.
+* Output data is grouped by output registers.
+
+Example:
+
+```python
+sampler.run([(circuit1, param_values1, shots1),(circuit2, param_values2, shots_2) ])
+```
## Estimator
-The Estimator primitive computes expectation values of observables with respect to states prepared by quantum circuits.
+The Estimator behaves differently, depending on what version you are using.
+
+
+
+ V2 Estimator computes expectation values of observables with respect to states prepared by quantum circuits.
+It receives one or more PUBs as the inputs and returns the computed expectation values per pair, along with their
+standard error, in `PubResult` form. 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.
+
+
+
+ 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.
+The Sampler behaves differently, depending on what version you are using.
+
+
+
+ V2 Sampler is simplified to focus on its core task of sampling the output register from execution of quantum circuits. It returns the samples, whose type is defined by the program, without weights and therefore does not support resilience levels. The result class, however, has methods to return weighted samples, such as counts.
+
+ It receives one or more PUBs as the inputs and returns counts or per-shot measurements, as `PubResult`s. The circuits
+can be parametrized, as long as the parameter values are also provided as input to the primitive.
+
+
+
+ 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.
+probabilities, except they might include negative values, which can occur when using certain error mitigation techniques.
+
+
## How to use Qiskit primitives
@@ -74,9 +165,9 @@ The `qiskit.primitives` module enables the development of primitive-style quantu
designed to simplify switching between different types of systems. The module provides three separate classes
for each primitive type:
-1. `Sampler` and `Estimator`
+1. `StatevectorSampler` and `StatevectorEstimator`
-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.
+These classes are reference implementations of both primitives and use the simulator built in to Qiskit. They leverage the Qiskit `quantum_info` module in the background, producing results based on ideal statevector simulations.
2. `BaseSampler` and `BaseEstimator`
@@ -86,12 +177,13 @@ These are abstract base classes that define a common interface for implementing
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.
+The Qiskit Runtime primitives provide a more sophisticated implementation (for example, by including error mitigation) as a cloud-based service.
## Next steps
- Read [Get started with primitives](primitives-get-started) to implement primitives in your work.
- Review detailed [primitives examples.](primitives-examples)
+ - Read [Migrate to V2 primitives](/api/migration-guides/v2-primitives).
- 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.
diff --git a/docs/run/quantum-serverless.mdx b/docs/run/quantum-serverless.mdx
index 2839312ce37..8ee3640e6dd 100644
--- a/docs/run/quantum-serverless.mdx
+++ b/docs/run/quantum-serverless.mdx
@@ -42,7 +42,7 @@ Here is an example of computing the expectation value using the Qiskit Runtime E
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 qiskit_ibm_runtime import QiskitRuntimeService
from quantum_serverless import save_result
service = QiskitRuntimeService()
@@ -57,17 +57,30 @@ 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
+# Step 3: Execute the target circuit on Estimator V1
+# from qiskit_ibm_runtime import Estimator
+# estimator = Estimator(backend)
+# job = estimator.run(target_circuit, target_observable)
+# result = job.result()
+
+# Step 3: Execute the target circuit on Estimator V2
+from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(backend)
-job = estimator.run(target_circuit, target_observable)
+job = estimator.run([(target_circuit, target_observable)])
result = job.result()
-# Step 4: Postprocess the results
-print(result)
+# Step 4: Postprocess the Estimator V1 results
+# print(result)
+# save results of program execution
+# note: saved items must be serializable
+# save_result(result.values)
+
+# Step 4: Postprocess the Estimator V2 results
+print(result)
# save results of program execution
# note: saved items must be serializable
-save_result(result.values)
+save_result(result[0].data.evs)
```
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).
@@ -120,7 +133,53 @@ For each `IBMQPUSelector`, the context is set in the constructor. All `IBMQPUSel
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
+
+
+ ```python
+# source_files/my_qiskit_pattern_resource_management.py
+
+from qiskit_ibm_runtime import QiskitRuntimeService, Session, Samplerv2 as Sampler
+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
+sampler = Sampler(backend=backend, options={"default_shots": 1024})
+job = sampler.run([(target_circuit,)])
+result = job.result()
+
+# Step 4: Postprocess the results
+print(f" > Counts: {result[0].data.meas.get_counts()}")
+
+# save results of program execution
+# note: saved items must be serializable
+save_result(result)
+```
+
+
+
+ ```python
# source_files/my_qiskit_pattern_resource_management.py
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Options
@@ -166,4 +225,7 @@ print(result)
save_result(result)
```
+
+
+
After creating this pattern, you can deploy and run it remotely with Quantum Serverless as described above.
diff --git a/docs/run/reserve-system-time.mdx b/docs/run/reserve-system-time.mdx
index 789771d4c67..7b16782e07c 100644
--- a/docs/run/reserve-system-time.mdx
+++ b/docs/run/reserve-system-time.mdx
@@ -6,7 +6,7 @@ description: Reserve time on a system as an IBM Quantum Network member
# Reserve system time
-
+
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.
diff --git a/docs/run/run-jobs-batch.mdx b/docs/run/run-jobs-batch.mdx
index bdb1923ef3f..bd54caef645 100644
--- a/docs/run/run-jobs-batch.mdx
+++ b/docs/run/run-jobs-batch.mdx
@@ -9,7 +9,7 @@ description: How to run quantum computing jobs in batch mode using Qiskit Runtim
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.
+- There is no delay between jobs, which can help avoid drift.
When batching, jobs are not guaranteed to run in the order they are submitted.
diff --git a/docs/run/run-jobs-in-session.mdx b/docs/run/run-jobs-in-session.mdx
index c88a4516682..36f82133273 100644
--- a/docs/run/run-jobs-in-session.mdx
+++ b/docs/run/run-jobs-in-session.mdx
@@ -27,45 +27,75 @@ service = QiskitRuntimeService()
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.
-
+
If the first session job is canceled, subsequent session jobs will all fail.
**Session class**
+
+
+``` python
+from qiskit_ibm_runtime import Session, Samplerv2 as Sampler, Estimatorv2 as Estimator
+
+backend = service.least_busy(operational=True, simulator=False)
+session = Session(service=service, backend=backend)
+estimator = Estimator(session=session)
+sampler = Sampler(session=session)
+```
+
+
+
``` python
from qiskit_ibm_runtime import Session, Sampler, Estimator
-session = Session(service=service, backend="ibmq_qasm_simulator")
+backend = service.least_busy(operational=True, simulator=False)
+session = Session(service=service, backend=backend)
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"):
+backend = service.least_busy(operational=True, simulator=False)
+with Session(service=service, backend=backend):
+ estimatorv2 = EstimatorV2()
+ samplerv2 = SamplerV2()
+```
+
+
+
+``` python
+backend = service.least_busy(operational=True, simulator=False)
+with Session(service=service, backend=backend):
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.
+When you start a session, you must specify a system. This can be done by specifying its name or by passing a `backend` object.
-**Specify a system or simulator by name**
+**Specify a system by name**
``` python
service = QiskitRuntimeService()
-with Session(service=service, backend="ibmq_qasm_simulator"):
+with Session(service=service, backend="ibm_sherbrooke"):
...
```
**Pass a `backend` object**
``` python
-backend = service.get_backend("ibmq_qasm_simulator")
+backend = service.least_busy(operational=True, simulator=False)
with Session(backend=backend):
...
```
@@ -73,7 +103,7 @@ with Session(backend=backend):
## 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.
+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"):
@@ -136,6 +166,27 @@ with Session(service=service, backend=backend) as 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, SamplerV2 as Sampler, EstimatorV2 as Estimator
+
+with Session(backend=backend):
+ sampler = Sampler()
+ estimator = Estimator()
+
+ job = sampler.run([(sampler_circuit,)])
+ result = job.result()
+ print(f" > Counts: {result[0].data.meas.get_counts()}")
+
+ job = estimator.run([(circuit, observable)])
+ result = job.result()
+ print(f" > Expectation value: {result[0].data.evs}")
+ print(f" > Metadata: {result[0].metadata}")
+```
+
+
+
```python
from qiskit_ibm_runtime import Session, Sampler, Estimator
@@ -148,7 +199,10 @@ with Session(backend=backend):
result = estimator.run(circuit, observable).result()
print(f">>> Expectation value from the estimator job: {result.values[0]}")
- ```
+```
+
+
+
## Check session status
@@ -166,16 +220,35 @@ Session status can be one of the following:
For a comprehensive overview of a session's configuration and status, use the `session.details() method`.
+
+
+``` python
+from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
+
+service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
+
+with Session(service=service, backend="backend") as session:
+ estimator = Estimator()
+ job = estimator.run([(circuit, observable)])
+ print(session.details())
+```
+
+
+
``` python
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
+backend = service.least_busy(operational=True, simulator=False)
-with Session(service=service, backend="ibmq_qasm_simulator") as session:
+with Session(service=service, backend=backend) as session:
estimator = Estimator()
job = estimator.run(circuit, observable)
print(session.details())
```
+
+
## Next steps
diff --git a/docs/start/hello-world.ipynb b/docs/start/hello-world.ipynb
index 2c5b86a1c32..aa7622c4435 100644
--- a/docs/start/hello-world.ipynb
+++ b/docs/start/hello-world.ipynb
@@ -66,6 +66,9 @@
],
"source": [
"from qiskit import QuantumCircuit\n",
+ "from qiskit.quantum_info import SparsePauliOp\n",
+ "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
+ "from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator\n",
"\n",
"# Create a new circuit with two qubits (first argument) and two classical\n",
"# bits (second argument)\n",
@@ -98,7 +101,7 @@
"id": "f3ef4248-7938-44c1-85f1-edc997f0edcd",
"metadata": {},
"source": [
- "The following code cell uses the `quantum_info` package to create the two-qubit Pauli operator Z on qubit 1 and Z on qubit 2. If the state is entangled, then the correlation between qubit 1 and qubit 2 is one."
+ "The following code cell uses the `quantum_info` package to create the two-qubit Pauli operator Z on qubit 0 and Z on qubit 1. If the state is entangled, then the correlation between qubit 0 and qubit 1 is one.\n"
]
},
{
@@ -108,46 +111,21 @@
"metadata": {},
"outputs": [],
"source": [
- "from qiskit.quantum_info import Pauli\n",
- "\n",
- "ZZ = Pauli('ZZ')\n",
- "ZI = Pauli('ZI')\n",
- "IZ = Pauli('IZ')\n",
- "XX = Pauli('XX')\n",
- "XI = Pauli('XI')\n",
- "IX = Pauli('IX')"
+ "# Set up six different observables.\n",
+ "observables_labels = [\"ZZ\", \"ZI\", \"IZ\", \"XX\", \"XI\"]\n",
+ "observables = [SparsePauliOp(label) for label in observables_labels]"
]
},
{
"cell_type": "markdown",
- "id": "88fe43f8",
+ "id": "674b4019",
"metadata": {},
"source": [
- "\n",
- "To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations; consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `options.transpilation.skip_transpilation`.\n",
+ "\n",
+ "To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables) before being submitted to the Qiskit Runtime primitives. See the [transpilation documentation](../transpile) for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. Users can still request that the primitives do no optimization of input circuits by specifying `optimization_level=0`.\n",
""
]
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7a5af409",
- "metadata": {},
- "outputs": [],
- "source": [
- "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
- "\n",
- "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
- "isa_circuit = pm.run(qc)\n",
- "ZZ = ZZ.apply_layout(isa_circuit.layout)\n",
- "ZI = ZI.apply_layout(isa_circuit.layout)\n",
- "ZI = ZI.apply_layout(isa_circuit.layout)\n",
- "IZ = IZ.apply_layout(isa_circuit.layout)\n",
- "XX = XX.apply_layout(isa_circuit.layout)\n",
- "IX = IX.apply_layout(isa_circuit.layout)\n",
- "XI = XI.apply_layout(isa_circuit.layout)"
- ]
- },
{
"cell_type": "markdown",
"id": "83bf9151-3bc9-40d2-8615-31570238b08e",
@@ -155,7 +133,7 @@
"source": [
"## Step 2. Optimize the circuits and operators\n",
"\n",
- "For this example, the circuit the operators are simple, so no optimizations are needed."
+ "For this example, the circuit and operators are simple, so no optimizations are needed. "
]
},
{
@@ -171,122 +149,113 @@
},
{
"cell_type": "code",
- "execution_count": 3,
- "id": "69a8d872",
+ "execution_count": null,
+ "id": "62c4ca44",
"metadata": {},
"outputs": [
{
- "data": {
- "text/plain": [
- "EstimatorResult(values=array([0.01795728, 0.03257367, 0.02751255, 0.01213789, 0.98291386,\n",
- " 0.97229465]), metadata=[{'variance': 1.0931623420576193, 'shots': 5008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.092423762099776, 'shots': 5008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.0256330625131442, 'shots': 5008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.0262426744136923, 'shots': 5008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 0.16516750416031306, 'shots': 5008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 0.18593026938419716, 'shots': 5008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}])"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'c:\\Python312\\python.exe' requires the ipykernel package.\n",
+ "\u001b[1;31mRun the following command to install 'ipykernel' into the Python environment. \n",
+ "\u001b[1;31mCommand: 'c:/Python312/python.exe -m pip install ipykernel -U --user --force-reinstall'"
+ ]
}
],
"source": [
- "from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options\n",
+ "# Construct the Estimator instance we want to use.\n",
"\n",
+ "# If you did not previously save your credentials, use the following line instead: \n",
+ "# service = QiskitRuntimeService(channel=\"ibm_quantum\", token=\"\")\n",
"service = QiskitRuntimeService()\n",
"\n",
"# Run on the least-busy backend you have access to\n",
"backend = service.least_busy(simulator=False, operational=True)\n",
"\n",
- "options = Options()\n",
- "options.resilience_level = 1\n",
- "options.optimization_level = 3\n",
- "\n",
- "# Create an Estimator object\n",
- "estimator = Estimator(backend, options=options)\n",
- "\n",
- "# Submit the circuit to Estimator\n",
- "job = estimator.run(circuits=[isa_circuit]*6, observables=[IZ, IX, ZI, XI, ZZ, XX], shots = 5000)\n",
+ "# Use the following code instead if you want to run on a simulator:\n",
+ "# backend = service.get_backend(\"ibmq_qasm_simulator\")\n",
"\n",
- "# Once the job is complete, get the result\n",
- "job.result()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e3ac728c",
- "metadata": {},
- "source": [
- "\n",
- " Queue times on real devices may vary. If you would like to get a faster result, replace the `backend =` line with the following instead:\n",
+ "estimator = Estimator(backend)\n",
+ "estimator.options.resilience_level = 1\n",
+ "estimator.options.execution.shots = 5000\n",
"\n",
- " ```python\n",
+ "# Convert to an ISA circuit and layout-mapped observables.\n",
+ "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
+ "isa_circuit = pm.run(qc)\n",
+ "observables = [\n",
+ " observable.apply_layout(isa_circuit.layout) for observable in observables\n",
+ "]\n",
"\n",
- " # Run on a simulator\n",
+ "# One pub, with one circuit to run against five different observables.\n",
+ "job = estimator.run([(isa_circuit, observables)])\n",
"\n",
- " backend = service.get_backend(\"ibmq_qasm_simulator\")\n",
+ "# This is the result of the entire submission. We submitted one Pub,\n",
+ "# so this contains one inner result (and some metadata of its own).\n",
+ "job_result = job.result()\n",
"\n",
- " ```\n",
- ""
+ "# This is the result from our single pub, which had five observables,\n",
+ "# so contains information on all five.\n",
+ "pub_result = job.result()[0]"
]
},
{
"cell_type": "markdown",
- "id": "dc5ce1eb",
+ "id": "0d5ea9a0",
"metadata": {},
"source": [
- "The `values` property is a list of expectation values for each of the observables we provided."
+ "## Step 4. Analyze the results"
]
},
{
"cell_type": "markdown",
- "id": "0d5ea9a0",
+ "id": "d200d1f8",
"metadata": {},
"source": [
- "## Step 4. Analyze the results"
+ "\n",
+ "You might need to run `pip install matplotlib` if you do not already have it installed.\n",
+ "\n",
+ "\n",
+ "The `values` property is a list of expectation values for each of the observables we provided."
]
},
{
"cell_type": "code",
- "execution_count": 4,
- "id": "57a82991-3ae9-400f-b8be-f8eb1fea79c5",
+ "execution_count": null,
+ "id": "87143fcc",
"metadata": {},
"outputs": [
{
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA+z0lEQVR4nO3deXyU5b3///fs2UMgELZIWBIFRaggCIooRnE5KJ6qHKTCoS6nrVqU028FUbH1KFoL4qlYXKq0v1rBavVQsVikQlCwFBBXZIcgkEACZCPrzPX7I5khMQGSMJl7ZvJ6Ph7zIPc998x8ZrjJvLmW+7IZY4wAAACihN3qAgAAAIKJcAMAAKIK4QYAAEQVwg0AAIgqhBsAABBVCDcAACCqEG4AAEBUcVpdQKj5fD4dOHBAiYmJstlsVpcDAACawRijkpISde/eXXb7qdtm2l24OXDggNLT060uAwAAtMK+ffvUs2fPUx7T7sJNYmKipNoPJykpyeJqAABAcxQXFys9PT3wPX4q7S7c+LuikpKSCDcAAESY5gwpYUAxAACIKoQbAAAQVQg3AAAgqhBuAABAVCHcAACAqEK4AQAAUYVwAwAAogrhBgAARBVLw01OTo7GjRun7t27y2az6Z133jntY1atWqULLrhAHo9H/fr106JFi9q8TgAAEDksDTdlZWUaNGiQFixY0Kzjd+/ereuuu06XX365Nm/erPvuu0933HGH3n///TauFAAARApLl1+45pprdM011zT7+IULF6p3796aO3euJKl///766KOP9Mwzz2js2LFtVSYAAIggETXmZt26dcrOzm6wb+zYsVq3bt1JH1NZWani4uIGNwAAEL0iKtzk5eUpLS2twb60tDQVFxervLy8ycfMmTNHycnJgVt6enooSgUAABaJqHDTGjNnzlRRUVHgtm/fPqtLAgCEms8r7V4jffFm7Z8+r9UVoQ1ZOuampbp27ar8/PwG+/Lz85WUlKTY2NgmH+PxeOTxeEJRHgAgHH29VPrbz6WSgyf2JXWXrn5KGnC9dXWhzURUy82IESO0cuXKBvtWrFihESNGWFQRACCsfb1UemNyw2AjScUHa/d/vdSautCmLA03paWl2rx5szZv3iypdqr35s2blZubK6m2S2ny5MmB43/0ox9p165d+vnPf65vvvlGzz//vN544w3df//9VpQP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TEFBQUhqa3cLZ7Yln8+nW2+9VU6nU6+99lrQVx1HLZvNpt/+9rfq37+/Bg4cqBkzZlhdUlThPG57nMNtrznncU5Oju677z49//zzGjlypAVVRrbmnMdjxozRTTfdpMWLF2vJkiXq1KlTSGpjQHEQPfjgg1q3bp3+7//+T4mJiVaXE9VeeeUVxcXFaffu3fr222+tLieqcB6HBudw2zrdeZybm6ubbrpJd911l+644w4LKowOpzuP9+/fr+XLlysuLk5r1qwJWV2EmyBZvHixfv3rX2vx4sXKzMy0upyotnbtWj3zzDN69913NWzYMN1+++0yrCISFJzHocE53LZOdx6Xl5frxhtv1Lnnnqv58+eHvsAo0Zzz+M4779SQIUP07rvv6re//W3oZqOFpPMrCtUfB/Lpp5+auLg48/TTT1tbVJSq/1mXlZWZzMxMc++99xpjascnJCQkmOeff97CCqPD6c5jxoIEx+nOYT7nM9Oc38e33nqrycjIMIcPHw5hZdGlOb+LX3rpJZOYmGj27NljjDHmnnvuMX369DGlpaVtXh/hppX8X7iHDx82vXr1Mtdee22TUxAPHTpkdakRr364+elPf2r69etnysrKAvcvXLjQJCQkmN27d1tTYBRoznnMl25wnO4c5nNuveacx7/61a+My+Uyy5cvb/KY48ePW/02IsLpzuM9e/aYxMRE88ILLwTuLysrM3379jX33HNPm9dHuGkl/xfuokWLjKST3nr16mV1qRHP/1mvWrXKOBwOs2bNmkbHXHXVVWbMmDHMUGul5pzHfOmeueacw7t27eJzbqXmnMcZGRmnPObVV1+1+m2Eveacx2PGjDFXXXVVo/vXrFljHA6HWbVqVZvWaDOGjl4AABA9GFAMAACiCuEGAABEFcINAACIKoQbAAAQVQg3AAAgqhBuAABAVCHcAACAqEK4AQAAUYVwAyDoMjIyInZBwssuu0z33XffKY+J5PcHtAeEGwAtsm/fPv3whz9U9+7d5Xa71atXL02bNk2FhYVWlwYAkgg3AFpg165dGjp0qLZv367XX39dO3bs0MKFC7Vy5UqNGDFCR44csaQur9crn89nyWsDCD+EGwDNdvfdd8vtduvvf/+7Ro8erbPOOkvXXHONPvjgA+3fv1+zZs0KHFtSUqKJEycqPj5ePXr00IIFCwL3GWP06KOP6qyzzpLH41H37t3105/+NHB/ZWWlfvazn6lHjx6Kj4/X8OHDtWrVqsD9ixYtUocOHbR06VINGDBAHo9HL7/8smJiYnTs2LEGNU+bNk1jxoyRJBUWFmrixInq0aOH4uLiNHDgQL3++uuN3mdNTY3uueceJScnKzU1VQ8//LBOtQzfsWPHdMcdd6hz585KSkrSmDFj9NlnnwXu/+yzz3T55ZcrMTFRSUlJGjJkiDZs2NDszx1AyxBuADTLkSNH9P777+snP/mJYmNjG9zXtWtXTZo0SUuWLAmEgKefflqDBg3Sp59+qhkzZmjatGlasWKFJOmtt97SM888oxdeeEHbt2/XO++8o4EDBwae75577tG6deu0ePFiff7557r55pt19dVXa/v27YFjjh8/rqeeekovv/yyvvrqK02aNEkdOnTQW2+9FTjG6/VqyZIlmjRpkiSpoqJCQ4YM0bJly/Tll1/qrrvu0m233ab169c3eD+///3v5XQ6tX79ej377LOaN2+eXn755ZN+NjfffLMOHTqkv/3tb9q4caMuuOACXXHFFYGWrEmTJqlnz57617/+pY0bN2rGjBlyuVyt+WsA0BxtuuY4gKjxySefGEnm7bffbvL+efPmGUkmPz/f9OrVy1x99dUN7p8wYYK55pprjDHGzJ0712RlZZmqqqpGz7N3717jcDjM/v37G+y/4oorzMyZM40xxrz66qtGktm8eXODY6ZNm2bGjBkT2H7//feNx+MxR48ePen7uu6668x///d/B7ZHjx5t+vfvb3w+X2DfAw88YPr37x/Y7tWrl3nmmWeMMcasWbPGJCUlmYqKigbP27dvX/PCCy8YY4xJTEw0ixYtOmkNAIKLlhsALWJO0T1T34gRIxptb9myRVJtS0d5ebn69OmjO++8U2+//bZqamokSV988YW8Xq+ysrKUkJAQuK1evVo7d+4MPJ/b7db555/f4DUmTZqkVatW6cCBA5Kk1157Tdddd506dOggqbYl57HHHtPAgQPVsWNHJSQk6P3331dubm6D57noootks9ka1L59+3Z5vd5G7/Ozzz5TaWmpOnXq1KDe3bt3B+qdPn267rjjDmVnZ+vJJ59s8D4ABJ/T6gIARIZ+/frJZrNpy5YtuvHGGxvdv2XLFqWkpKhz586nfa709HRt3bpVH3zwgVasWKGf/OQnevrpp7V69WqVlpbK4XBo48aNcjgcDR6XkJAQ+Dk2NrZBAJGkCy+8UH379tXixYv14x//WG+//bYWLVoUuP/pp5/Ws88+q/nz52vgwIGKj4/Xfffdp6qqqhZ+GieUlpaqW7duDcYE+flD1aOPPqpbb71Vy5Yt09/+9jfNnj1bixcvbvJzBHDmCDcAmqVTp0668sor9fzzz+v+++9vMO4mLy9Pr732miZPnhwIHJ988kmDx3/yySfq379/YDs2Nlbjxo3TuHHjdPfdd+ucc87RF198oe9973vyer06dOiQRo0a1eI6J02apNdee009e/aU3W7XddddF7jv448/1g033KAf/OAHkiSfz6dt27ZpwIABDZ7jn//8Z6PaMzMzG4UtSbrggguUl5cnp9OpjIyMk9aVlZWlrKws3X///Zo4caJeffVVwg3QRuiWAtBszz33nCorKzV27Fjl5ORo3759Wr58ua688kr16NFDjz/+eODYjz/+WL/61a+0bds2LViwQH/+8581bdo0SbWznX73u9/pyy+/1K5du/THP/5RsbGx6tWrl7KysjRp0iRNnjxZf/nLX7R7926tX79ec+bM0bJly05b46RJk7Rp0yY9/vjjuummm+TxeAL3ZWZmasWKFVq7dq22bNmi//qv/1J+fn6j58jNzdX06dO1detWvf766/rNb34TqP27srOzNWLECI0fP15///vftWfPHq1du1azZs3Shg0bVF5ernvuuUerVq3S3r179fHHH+tf//pXg6AHIMisHvQDILLs2bPHTJkyxaSlpRmXy2XS09PNvffeawoKCgLH9OrVy/ziF78wN998s4mLizNdu3Y1zz77bOD+t99+2wwfPtwkJSWZ+Ph4c9FFF5kPPvggcH9VVZV55JFHTEZGhnG5XKZbt27mxhtvNJ9//rkxpnZAcXJy8klrHDZsmJFk/vGPfzTYX1hYaG644QaTkJBgunTpYh566CEzefJkc8MNNwSOGT16tPnJT35ifvSjH5mkpCSTkpJiHnzwwQYDjOsPKDbGmOLiYnPvvfea7t27Bz6TSZMmmdzcXFNZWWn+4z/+w6Snpxu32226d+9u7rnnHlNeXt7Sjx5AM9mMaeboQAAAgAhAtxQAAIgqhBsAABBVCDcAACCqEG4AAEBUIdwAAICoQrgBAABRhXADAACiCuEGAABEFcINAACIKoQbAAAQVQg3AAAgqvz/AUTBK1hc4kUAAAAASUVORK5CYII=",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'c:\\Python312\\python.exe' requires the ipykernel package.\n",
+ "\u001b[1;31mRun the following command to install 'ipykernel' into the Python environment. \n",
+ "\u001b[1;31mCommand: 'c:/Python312/python.exe -m pip install ipykernel -U --user --force-reinstall'"
+ ]
}
],
"source": [
- "import matplotlib.pyplot as plt\n",
- "import numpy as np\n",
+ "# Plot the result\n",
+ "\n",
+ "from matplotlib import pyplot as plt\n",
"\n",
- "# data\n",
- "data = ['IZ', 'IX', 'ZI', 'XI', 'ZZ', 'XX']\n",
- "values = job.result().values\n",
+ "data = observables_labels\n",
+ "values = pub_result.data.evs\n",
"\n",
- "# creating error bars\n",
- "error = []\n",
- "for case in job.result().metadata:\n",
- " error.append(2*np.sqrt(case['variance']/case['shots']))\n",
+ "errors = pub_result.data.ensemble_standard_error\n",
"\n",
- "# plotting graph\n",
- "plt.plot(data, values)\n",
- "plt.errorbar(data, values, yerr = error, fmt ='o')\n",
- "plt.xlabel('Observables')\n",
- "plt.ylabel('Values')\n",
- "plt.show()"
+ "plt.errorbar(observables_labels, values, yerr=errors, fmt=\"o\")"
]
},
{
"cell_type": "markdown",
- "id": "b9a76788-3c34-4382-88f1-fc7ce9dc7234",
+ "id": "e6a9ba84",
"metadata": {},
"source": [
- "Here we see that for qubits 0 and 1, the independent values of both X and Z are zero, while the correlations are one. This is a hallmark of quantum entanglement."
+ "Here we see that for qubits 0 and 1, the independent values of both X and Z are 0, while the correlations are 1. This is a hallmark of quantum entanglement."
]
},
{
@@ -321,7 +290,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3"
+ "version": "3.12.0"
},
"title": "Hello world"
},
diff --git a/docs/start/index.mdx b/docs/start/index.mdx
index 65f93817cfd..6bfe37f930e 100644
--- a/docs/start/index.mdx
+++ b/docs/start/index.mdx
@@ -28,7 +28,7 @@ Already know what you’re looking for?
- [Run](../run): Run on our hardware with job configuration options such as sessions.
-- **API reference**: Find API references for [Qiskit](/api/qiskit), [Qiskit Runtime IBM Client](/api/qiskit-ibm-runtime), [Qiskit IBM Runtime REST API](/api/runtime/), and [Qiskit IBM Provider](/api/qiskit-ibm-provider) in the API reference drop-down menu above. You can also find the [Error code registry](../errors) here.
+- **API reference**: Find API references for [Qiskit](/api/qiskit), [Qiskit Runtime IBM Client](/api/qiskit-ibm-runtime), [Qiskit IBM Runtime REST API](/api/runtime/), and [Qiskit IBM Provider](/api/qiskit-ibm-provider) in the API reference drop-down menu above. You can also find the [Error code registry](../errors) and [migration guides](/api/migration-guides) here.
## Community
diff --git a/docs/start/setup-channel.mdx b/docs/start/setup-channel.mdx
index c3d2f118eec..5f35b215c5b 100644
--- a/docs/start/setup-channel.mdx
+++ b/docs/start/setup-channel.mdx
@@ -55,7 +55,7 @@ You need access credentials to use cloud-based IBM Quantum systems.
python3
```
-1. Authenticate to the service by calling `QiskitRuntimeService` with your IBM Cloud API key and CRN:
+1. Authenticate to the service by calling `QiskitRuntimeService` with your IBM Quantum API key and CRN:
```python
from qiskit_ibm_runtime import QiskitRuntimeService
@@ -92,24 +92,26 @@ You need access credentials to use cloud-based IBM Quantum systems.
1. Test your setup. Run a simple circuit using Sampler to ensure that your environment is set up properly:
- ```python
- from qiskit import QuantumCircuit
- from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
+ ```python
+from qiskit import QuantumCircuit
+from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
- # Create empty circuit
- example_circuit = QuantumCircuit(2)
- example_circuit.measure_all()
+# Create empty circuit
+example_circuit = QuantumCircuit(2)
+example_circuit.measure_all()
- # You'll need to specify the credentials when initializing QiskitRuntimeService, if they were not previously saved.
- 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)
- ```
+# You'll need to specify the credentials when initializing QiskitRuntimeService, if they were not previously saved.
+service = QiskitRuntimeService()
+backend = service.backend("ibmq_qasm_simulator")
+
+sampler = Sampler(backend)
+job = sampler.run([(example_circuit,)])
+print(f"job id: {job.job_id()}")
+result = job.result()
+print(result)
+ ```
-
+
## Set up to use IBM Cloud
1. Start Python. For example:
@@ -169,7 +171,7 @@ You need access credentials to use cloud-based IBM Quantum systems.
```python
from qiskit import QuantumCircuit
- from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
+ from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
# Create empty circuit
example_circuit = QuantumCircuit(2)
@@ -178,7 +180,8 @@ You need access credentials to use cloud-based IBM Quantum systems.
# You'll need to specify the credentials when initializing QiskitRuntimeService, if they were not previously saved.
service = QiskitRuntimeService()
backend = service.backend("ibmq_qasm_simulator")
- job = Sampler(backend).run(example_circuit)
+ sampler = Sampler(backend)
+ job = sampler.run([(example_circuit,)])
print(f"job id: {job.job_id()}")
result = job.result()
print(result)
diff --git a/public/images/build/options.png b/public/images/build/options.png
deleted file mode 100644
index 39a69a56ade..00000000000
Binary files a/public/images/build/options.png and /dev/null differ
diff --git a/public/images/optimize/resiliance-2.png b/public/images/optimize/resilience-2.png
similarity index 100%
rename from public/images/optimize/resiliance-2.png
rename to public/images/optimize/resilience-2.png
diff --git a/public/images/run/options.png b/public/images/run/options.png
new file mode 100644
index 00000000000..32423d93c7b
Binary files /dev/null and b/public/images/run/options.png differ