From f52fe7ee38d385353438c419cb851ceaaa9e2655 Mon Sep 17 00:00:00 2001 From: Rebecca Dimock Date: Wed, 14 Feb 2024 14:54:21 -0600 Subject: [PATCH 01/60] draft changes --- .../simulate-with-qiskit-primitives.mdx | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f1ccc27e302..a98c2a353f5 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -14,7 +14,7 @@ The `Estimator` primitive can compute an expectation value, and the `Sampler` pr Follow these instructions to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive. - While this guide uses Qiskit’s reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). + While this guide uses the Qiskit reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). ```python from qiskit.primitives import BackendEstimator @@ -71,29 +71,61 @@ estimator = Estimator() ### Run and get results Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, -which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) +which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). + +The V2 primitives take one or more primitive unified blocs (PUBs) as the inputs. Each PUB is a tuple that contains a single circuit and data broadcasted to that circuit. + + + + ```python +job = estimator.run([(qc, observable)]) +result = job.result() +print(result) +``` + +You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python +print(f" > Metadata: {result[0].metadata}") +``` + + + ```python job = estimator.run(qc, observable) result = job.result() print(result) ``` +You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) +with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python EstimatorResult(values=array([4.]), metadata=[{}]) ``` + + + + This example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable. If you want to get expectation values for multiple circuits and observables, you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length. #### Get the expected value -From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values). + + + + ```python +print(f" > Expectation value: {result[0].data.evs}") +print(f" > Metadata: {result[0].metadata}") +``` + + + From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values). [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray` whose `i`th element is the expectation value corresponding to the `i`th circuit and `i`th observable. -```python + ```python exp_value = result.values[0] print(exp_value) ``` @@ -101,6 +133,8 @@ print(exp_value) ```python 3.999999999999999 ``` + + ### Parameterized circuit with `Estimator` From 49d73ac7768c58329a5893e7832875d01b3ed6a8 Mon Sep 17 00:00:00 2001 From: Rebecca Dimock <66339736+beckykd@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:46:53 -0600 Subject: [PATCH 02/60] Update docs/verify/simulate-with-qiskit-primitives.mdx Co-authored-by: Ian Hincks --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index a98c2a353f5..f842b23c5de 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -71,7 +71,7 @@ estimator = Estimator() ### Run and get results Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, -which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). +which returns an instance of [`qiskit.primitives.PrimitiveJob`](../api/qiskit/qiskit.primitives.PrimitiveJob). The V2 primitives take one or more primitive unified blocs (PUBs) as the inputs. Each PUB is a tuple that contains a single circuit and data broadcasted to that circuit. From aea5053c1698a779579d5d2ddb4e9820ce322828 Mon Sep 17 00:00:00 2001 From: Rebecca Dimock <66339736+beckykd@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:47:18 -0600 Subject: [PATCH 03/60] Update docs/verify/simulate-with-qiskit-primitives.mdx Co-authored-by: Ian Hincks --- docs/verify/simulate-with-qiskit-primitives.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f842b23c5de..f5cabd7c63e 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -74,6 +74,7 @@ Now that you have defined your `estimator`, you can run your estimation by calli which returns an instance of [`qiskit.primitives.PrimitiveJob`](../api/qiskit/qiskit.primitives.PrimitiveJob). The V2 primitives take one or more primitive unified blocs (PUBs) as the inputs. Each PUB is a tuple that contains a single circuit and data broadcasted to that circuit. +The following example just uses a single observable, but a list or array of observables could be used instead, and an expectation value would be returned for each one. From 89fab90d46fd4c35faf4036aaf60426ebdb2a81c Mon Sep 17 00:00:00 2001 From: Rebecca Dimock Date: Wed, 14 Feb 2024 18:25:25 -0600 Subject: [PATCH 04/60] further edits --- .../simulate-with-qiskit-primitives.mdx | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index a98c2a353f5..4a9c6b3d526 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -7,14 +7,14 @@ description: Simulate with Qiskit reference primitives. How to compute an expect The reference primitives in Qiskit® can perform local statevector simulations, which is useful for quickly prototyping algorithms. -The `Estimator` primitive can compute an expectation value, and the `Sampler` primitive can compute circuit output probabilities. +The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample from output distributions of circuits. ## Compute an expectation value with the `Estimator` primitive Follow these instructions to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive. - While this guide uses the Qiskit reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). + While this guide uses the Qiskit reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). There is not yet an equivalent implementation in V2, but it is coming soon. ```python from qiskit.primitives import BackendEstimator @@ -30,8 +30,8 @@ Follow these instructions to get the expected value of an observable for a given ### Initialize observables -The first step is to define the observables whose expected value you want to compute. Each observable can be any `BaseOperator`, like the operators from [`qiskit.quantum_info`](../api/qiskit/quantum_info). -Among them it is preferable to use [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). +The first step is to define the observables whose expected values you want to compute. Each observable can be a Pauli string, a dictionary mapping Pauli strings to real coefficients, or a [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). +In this example, we define a single observable, but in general, you can attach many observables to a single circuit. ```python from qiskit.quantum_info import SparsePauliOp @@ -60,37 +60,54 @@ qc.draw("mpl", style="iqp") ### Initialize `Estimator` -Next, instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). + + + Next, instantiate an [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). + +```python +from qiskit.primitives import StatevectorEstimator +estimator = StatevectorEstimator() +``` + + + + Next, instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). ```python from qiskit.primitives import Estimator estimator = Estimator() ``` + + -### Run and get results - -Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, -which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). -The V2 primitives take one or more primitive unified blocs (PUBs) as the inputs. Each PUB is a tuple that contains a single circuit and data broadcasted to that circuit. +### Run and get results + Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). + + The V2 primitives take one or more primitive unified blocs (PUBs) as the inputs. Each PUB is a tuple that contains a single circuit and data broadcasted to that circuit. + ```python job = estimator.run([(qc, observable)]) result = job.result() print(result) ``` -You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) -with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. +You can get the results from the job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) +with the [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.pprimitives.PrimitiveJob.result) method. ```python print(f" > Metadata: {result[0].metadata}") ``` + Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, +which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). + + ```python job = estimator.run(qc, observable) result = job.result() From c155618bd34869fa19a29c2e0a2832acd0601344 Mon Sep 17 00:00:00 2001 From: Rebecca Dimock Date: Thu, 15 Feb 2024 16:23:51 -0600 Subject: [PATCH 05/60] Further edits --- .../simulate-with-qiskit-primitives.mdx | 298 +++++++++++++++--- 1 file changed, 258 insertions(+), 40 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 4a9c6b3d526..b8a7457fb07 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -84,27 +84,26 @@ estimator = Estimator() ### Run and get results - - - Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). +This example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable. - The V2 primitives take one or more primitive unified blocs (PUBs) as the inputs. Each PUB is a tuple that contains a single circuit and data broadcasted to that circuit. +* For V1 primitives, if you want to get expectation values for multiple circuits and observables, you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length. - ```python -job = estimator.run([(qc, observable)]) -result = job.result() -print(result) -``` +* The V2 primitives accept **vectorized inputs**, where single circuits can be grouped with array-valued specifications. That is, one circuit can be executed + for arrays of `n` parameter sets, `n` observables, or both (in the case of the estimator). Each group is called a **primitive unified bloc (PUB)**, and can be represented as a tuple: `(1 x circuit, [n x observables], [n x parameters])`. Each PUB gets its own result. -You can get the results from the job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) -with the [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.pprimitives.PrimitiveJob.result) method. + + + Run the estimation by calling the [`qiskit.primitives.StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method. ```python +job = estimator.run([(qc, observable)]) +result = job.result()[0].data.evs + print(f" > Metadata: {result[0].metadata}") ``` - Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, + Run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). @@ -122,10 +121,6 @@ EstimatorResult(values=array([4.]), metadata=[{}]) - - -This example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable. If you want to get expectation values for multiple circuits and observables, you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length. - #### Get the expected value @@ -176,7 +171,23 @@ q_1: ─────────┤ X ├ └───┘ ``` -The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. + + + ```python +import numpy as np + +parameter_values = [[0], [np.pi/6], [np.pi/2]] + +job = estimator.run([(param_qc, [[obs1, obs2, obs3]], [parameter_values])]) + +values = job.result()[0].data.evs + +print(f"Parameter: {parameter_values[0]:.5f}\t Expectation value: {result[0].data.evs}") +``` + + + + The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit and observable. ```python @@ -196,23 +207,65 @@ Parameter: 0.00000 Expectation value: 2.0 Parameter: 0.52360 Expectation value: 3.0 Parameter: 1.57080 Expectation value: 4.0 ``` + + ### Change run options Your workflow might require tuning primitive run options, such as the number of shots. -By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact statevector calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be modified to include shot noise if the number of `shots` is set. For reproducibility purposes, a `seed` will also be set in the following examples. + + + The sampling overhead, commonly exposed by V1 implementations + through the `shots` run option, is now an argument of the primitives `run()` method + that can be specified at the **PUB** level. + The V2 base classes expose the arguments in formats different from the V1 API: + + * [`BaseSamplerV2.run`](/api/qiskit/qiskit.primitives.BaseSamplerV2#run) + exposes a `shots` argument (similar to the previous workflow): + + ```python + # Sample two circuits at 128 shots each. + sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) + ``` + + * [`EstimatorV2.run`](/api/qiskit/qiskit.primitives.BaseEstimatorV2#run) + introduces a `precision` argument that specifies the error bars that the + primitive implementation should target for expectation values estimates: + ```python + # Estimate expectation values for two PUBs, both with 0.05 precision. + estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) + ``` + + + + By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact statevector calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be modified to include shot noise if the number of `shots` is set. For reproducibility purposes, a `seed` will also be set in the following examples. There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator): -- Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. -- Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. + - Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. + - Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. + + #### Set keyword arguments for [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by passing them as keyword arguments. -```python + + + ```python + # Estimate expectation values for two PUBs, both with 0.05 precision. + estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) + ``` + + + + ```python job = estimator.run(qc, observable, shots=2048, seed=123) result = job.result() print(result) @@ -229,6 +282,8 @@ print(result.values[0]) ```python 3.999999998697238 ``` + + #### Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options @@ -239,6 +294,12 @@ rewrite the configuration values every time you use [`qiskit.primitives.Estimato If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments. +V1 primitives example: + + + For V2 primitives, `shots` is now an argument of the primitives `run()` method. + + ```python estimator.set_options(shots=2048, seed=123) @@ -263,7 +324,31 @@ print(result.values[0]) If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, define a `dict` like this one: -```python + + + + For V2 primitives, `shots` is an argument of the primitives `run()` method, although you can specify different options, such as `optimization_level`. + + **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?** + + + ```python +from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options + +service = QiskitRuntimeService() +options = Options() +options.resilience_level = 2 +options.optimization_level = 1 +backend = service.backend("ibmq_qasm_simulator") + +estimator = Estimator(options=options, backend=backend) +job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1]) +psi1_H1 = job.result() +``` + + + + ```python options = {"shots": 2048, "seed": 123} ``` @@ -288,12 +373,15 @@ print(result.values[0]) ```python 3.999999998697238 ``` + + + ## Compute circuit output probabilities with `Sampler` primitive Follow these instructions to get the probability distribution of a quantum circuit with the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive. - While this guide uses Qiskit’s reference implementation, the `Sampler` primitive can be run with any provider using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). + While this guide uses the Qiskit reference implementation, the `Sampler` primitive can be run with any provider using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). ```python from qiskit.primitives import BackendSampler @@ -331,17 +419,50 @@ The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircui Next, create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance. -```python + + + + ```python +from qiskit.primitives import StatevectorSampler + +sampler = StatevectorSampler() +``` + + + + ```python from qiskit.primitives import Sampler sampler = Sampler() ``` + + ### Run and get results -Now that you have defined your `sampler`, run it by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. +Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. + + + + ```python +# execute 1 circuit with 3 parameter sets using Sampler V2 +job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) +counts = job.result()[0].data.meas.get_counts() +``` + V2 primitives accept multiple PUBs as inputs, and each pub gets its own result. This + lets you run different circuits with various parameter/observable combinations, + which was not always possible in the V1 interface: ```python +# execute 2 circuits with 1 parameter set using Sampler V2 +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) +``` + + + + ```python job = sampler.run(qc) result = job.result() print(result) @@ -352,12 +473,50 @@ SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], meta ``` While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), you can sample multiple circuits by passing a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. + + -### Get the probability distribution +### Get the probability distribution or measurement outcome -From these results you can extract the quasi-probability distributions with the attribute [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists). +From these results you can extract the quasi-probability distributions (V1) with the attribute [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists). The V2 sampler returns measurement outcome samples in the form of **bitstrings** or + **counts**. The bitstrings show the measurement outcomes, preserving the shot + order in which they were measured. The V2 sampler result objects organize + data in terms of their input circuits' classical register names, for + compatibility with dynamic circuits. -Even though there is only one circuit in this example, [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists) returns a list of [`qiskit.result.QuasiDistribution`](../api/qiskit/qiskit.result.QuasiDistribution)s. + + + The name of the classical register defaults to `"meas"`. + This name will be used later to access the measurement bitstrings. + + ```python + # Define quantum circuit with 2 qubits + circuit = QuantumCircuit(2) + circuit.h(0) + circuit.cx(0, 1) + circuit.measure_all() + circuit.draw() + ``` + ```python + # Run using V2 sampler + result = sampler_v2.run([circuit]).result() + # Access result data for pub 0 + data_pub = result[0].data + # Access bitstring for the classical register "meas" + bitstring = data_pub.meas.get_bitstring() + print(f"The bitstring shape is: {bitstring.shape}") + # Get counts for the classical register "meas" + counts = data_pub.meas.get_counts() + print(f"The counts are: {counts}") + ``` + ```text + The bitstring shape is: (1024, 1) + The counts are: {'00': 523, '11': 501} + ``` + + + + Even though there is only one circuit in this example, [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists) returns a list of [`qiskit.result.QuasiDistribution`](../api/qiskit/qiskit.result.QuasiDistribution)s. `result.quasi_dists[i]` is the quasi-probability distribution of the `i`th circuit. @@ -365,17 +524,29 @@ A quasi-probability distribution differs from a probability distribution in that However, the quasi-probabilities must sum up to 1 like probabilities. Negative quasi-probabilities may appear when using error mitigation techniques. + ```python + # Define quantum circuit with 2 qubits + circuit = QuantumCircuit(2) + circuit.h(0) + circuit.cx(0, 1) + circuit.measure_all() + circuit.draw() + ``` -```python -quasi_dist = result.quasi_dists[0] -print(quasi_dist) -``` + ```python + # Run using V1 sampler + result = sampler_v1.run(circuit).result() + quasi_dist = result.quasi_dists[0] + print(f"The quasi-probability distribution is: {quasi_dist}") + ``` + ```text + The quasi-probability distribution is: {0: 0.5, 3: 0.5} + ``` + + -```python -{0: 0.4999999999999999, 3: 0.4999999999999999} -``` -#### Probability distribution with binary outputs +#### Probability distribution with binary outputs (V1) If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. @@ -413,7 +584,22 @@ print(param_qc.draw(style="iqp")) 0 1 ``` -The main difference from the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit. + + + + + ```python + # run 1 circuit with 3 parameter sets using Sampler V2 + job = sampler_v2.run([(param_qc, parameter_values)]) + result = job.result() + + # Get counts for the classical register "meas" + print(f"Parameter: {parameter_values[0]:.5f}\t Counts: {result[0].data.evs}") + ``` + + + + The main difference from the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit. ```python import numpy as np @@ -432,6 +618,10 @@ Parameter: 0.00000 Probabilities: {0: 1.0} Parameter: 0.52360 Probabilities: {0: 0.9330127018922194, 3: 0.0669872981077807} Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.4999999999999999} ``` + + + + ### Change run options @@ -451,7 +641,22 @@ There are two main ways of setting options in the [`qiskit.primitives.Sampler`]( If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by passing them as keyword arguments. -```python + + + + + ```python +# Sample two circuits at 128 shots each. +sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) +``` + + + + ```python job = sampler.run(qc, shots=2048, seed=123) result = job.result() print(result) @@ -460,12 +665,14 @@ print(result) ```python SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) ``` + + #### Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run). -#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) +#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) (V1) If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use [`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments. @@ -483,7 +690,15 @@ SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shot #### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options -If you prefer to define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options, define a `dict` like this one: +If you prefer, you can define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options. + + + + **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?** + + + + Define a `dict` like this one: ```python options = {"shots": 2048, "seed": 123} @@ -503,6 +718,9 @@ print(result) SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) ``` + + + ## Next steps From a19b05aea29422e0336f58145ba87a0c2794ffc0 Mon Sep 17 00:00:00 2001 From: Rebecca Dimock Date: Mon, 19 Feb 2024 14:13:41 -0600 Subject: [PATCH 06/60] pull out backend primitives --- docs/run/primitives-get-started.mdx | 31 ++++++++++++++++++- .../simulate-with-qiskit-primitives.mdx | 29 ----------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/run/primitives-get-started.mdx b/docs/run/primitives-get-started.mdx index d2d3157e90a..d28be36420b 100644 --- a/docs/run/primitives-get-started.mdx +++ b/docs/run/primitives-get-started.mdx @@ -13,7 +13,7 @@ To ensure faster and more efficient results, as of 1 March 2024, circuits and ob - These examples all use the primitives from Qiskit® Runtime, but you could use the base primitives instead. + While this documentation uses the primitives from Qiskit® Runtime, which allow you to use IBM® backends, the primitives can be run on any provider by using the [backend primitives](#backend) instead. Additionally, you can use the *reference* primitives to run on a local statevector simulator. See [Exact simulation with Qiskit primitives](../verify/simulate-with-qiskit-primitives) for details. @@ -154,6 +154,35 @@ print(f">>> {result}") print(f" > Quasi-probability distribution: {result.quasi_dists[0]}") print(f" > Metadata: {result.metadata[0]}") ``` + +## Get started with the backend primitives + +The `Sampler` primitive can be run with any provider by using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). Likewise, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). There are not yet equivalent implementations in V2, but they are coming soon. + +There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details). + +### Example: BackendEstimator + + ```python + from qiskit.primitives import BackendEstimator + from import QiskitProvider + + provider = QiskitProvider() + backend = provider.get_backend('backend_name') + estimator = BackendEstimator(backend) + ``` + +### Example: BackendSampler + + ```python + from qiskit.primitives import BackendSampler + from import QiskitProvider + + provider = QiskitProvider() + backend = provider.get_backend('backend_name') + sampler = BackendSampler(backend) + ``` + ## Next steps diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index b8a7457fb07..11b6cc8e02f 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -13,21 +13,6 @@ The `Estimator` primitive can compute expectation values of circuits, and the `S Follow these instructions to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive. - - While this guide uses the Qiskit reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). There is not yet an equivalent implementation in V2, but it is coming soon. - - ```python - from qiskit.primitives import BackendEstimator - from import QiskitProvider - - provider = QiskitProvider() - backend = provider.get_backend('backend_name') - estimator = BackendEstimator(backend) - ``` - - There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem/#primitives) for more details). - - ### Initialize observables The first step is to define the observables whose expected values you want to compute. Each observable can be a Pauli string, a dictionary mapping Pauli strings to real coefficients, or a [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). @@ -380,20 +365,6 @@ print(result.values[0]) Follow these instructions to get the probability distribution of a quantum circuit with the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive. - - While this guide uses the Qiskit reference implementation, the `Sampler` primitive can be run with any provider using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). - - ```python - from qiskit.primitives import BackendSampler - from import QiskitProvider - - provider = QiskitProvider() - backend = provider.get_backend('backend_name') - sampler = BackendSampler(backend) - ``` - - There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details). - ### Initialize QuantumCircuit From 68bef1d0b0d104cd9b99d8494b7cd674cb30b677 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Mon, 1 Apr 2024 14:33:25 -0400 Subject: [PATCH 07/60] clean up after merge conflict --- docs/run/primitives-get-started.mdx | 31 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/docs/run/primitives-get-started.mdx b/docs/run/primitives-get-started.mdx index 18dda13468f..91915bfbc81 100644 --- a/docs/run/primitives-get-started.mdx +++ b/docs/run/primitives-get-started.mdx @@ -231,6 +231,9 @@ print(f">>> {result}") print(f" > Quasi-probability distribution: {result.quasi_dists[0]}") print(f" > Metadata: {result.metadata[0]}") ``` + + + ## Get started with the backend primitives @@ -240,25 +243,25 @@ There are some providers that implement primitives natively (see [the Qiskit Eco ### Example: BackendEstimator - ```python - from qiskit.primitives import BackendEstimator - from import QiskitProvider +```python +from qiskit.primitives import BackendEstimator +from import QiskitProvider - provider = QiskitProvider() - backend = provider.get_backend('backend_name') - estimator = BackendEstimator(backend) - ``` +provider = QiskitProvider() +backend = provider.get_backend('backend_name') +estimator = BackendEstimator(backend) +``` ### Example: BackendSampler - ```python - from qiskit.primitives import BackendSampler - from import QiskitProvider +```python +from qiskit.primitives import BackendSampler +from import QiskitProvider - provider = QiskitProvider() - backend = provider.get_backend('backend_name') - sampler = BackendSampler(backend) - ``` +provider = QiskitProvider() +backend = provider.get_backend('backend_name') +sampler = BackendSampler(backend) +``` ## Next steps From d7c0f740f42d07ba267dddc41963cb9ff4c2b946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 4 Apr 2024 18:00:07 +0200 Subject: [PATCH 08/60] Add Elena's suggestion for simulate with primitives topic (starting point) --- .../simulate-with-qiskit-primitives.mdx | 988 +++++++++++------- 1 file changed, 612 insertions(+), 376 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 4de585bd715..009658606f2 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -5,49 +5,123 @@ description: How to perform exact simulation of quantum circuits using primitive # Exact simulation with Qiskit primitives -The reference primitives in Qiskit can perform local statevector simulations, which is useful for quickly prototyping algorithms. +The reference primitives in Qiskit® perform local statevector simulations. These simulations do not support +modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation +techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives). -The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample from output distributions of circuits. +The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample +from output distributions of circuits. -## Compute an expectation value with the `Estimator` primitive +The following sections show how to use the reference primitives to run your workflow locally. -Follow these instructions to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive. +[//]: # () +[//]: # () -### Initialize observables +[//]: # ( While this guide uses the Qiskit reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). There is not yet an equivalent implementation in V2, but it is coming soon.) -The first step is to define the observables whose expected values you want to compute. Each observable can be a Pauli string, a dictionary mapping Pauli strings to real coefficients, or a [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). -In this example, we define a single observable, but in general, you can attach many observables to a single circuit. +[//]: # () +[//]: # ( ```python) -```python -from qiskit.quantum_info import SparsePauliOp +[//]: # ( from qiskit.primitives import BackendEstimator) -observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) -``` +[//]: # ( from import QiskitProvider) + +[//]: # () +[//]: # ( provider = QiskitProvider()) + +[//]: # ( backend = provider.get_backend('backend_name')) + +[//]: # ( estimator = BackendEstimator(backend)) + +[//]: # ( ```) + +[//]: # () +[//]: # ( There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem/#primitives) for more details).) + +[//]: # () + +[//]: # () +[//]: # () + +[//]: # ( While this guide uses the Qiskit reference implementation, the `Sampler` primitive can be run with any provider using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler).) + +[//]: # () +[//]: # ( ```python) + +[//]: # ( from qiskit.primitives import BackendSampler) + +[//]: # ( from import QiskitProvider) + +[//]: # () +[//]: # ( provider = QiskitProvider()) + +[//]: # ( backend = provider.get_backend('backend_name')) + +[//]: # ( sampler = BackendSampler(backend)) + +[//]: # ( ```) + +[//]: # () +[//]: # ( There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details).) -### Initialize QuantumCircuit +[//]: # () -Next, create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) for which you want to obtain the expected value. + +## Use the reference `Estimator` + +There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector +simulators, the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the +[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) +implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization +features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the +legacy Estimator V1 interface. Both can take circuits, observables and parameters as inputs and return the locally +computed expectation values. + +The following code prepares the inputs that will be used in the examples below. The expected input type for the +observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that +the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits. + +[//]: # ( The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s.) + +[//]: # (The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit and observable.) + + + Any circuit passed to an Estimator must **not** include any **measurements**. + ```python from qiskit import QuantumCircuit +from qiskit.circuit import Parameter +from qiskit.quantum_info import SparsePauliOp +# circuit for which you want to obtain the expected value qc = QuantumCircuit(2) +qc.ry(Parameter('theta'), 0) qc.h(0) qc.cx(0,1) qc.draw("mpl", style="iqp") + +# observable(s) whose expected values you want to compute +observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) + +# value(s) for the circuit parameter(s) +import numpy as np +theta_values = [[0], [np.pi/6], [np.pi/2]] ``` +Note: fix circuit image (doesn't correspond to code) ![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png "Initial QuantumCircuit") - - The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) must not include any measurements. - +### Initialize an Estimator -### Initialize `Estimator` +To use the Estimator V2 implementation, follow the instructions to instantiate a +[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain +your pre-existing workflow using an Estimator V1 implementation, you can also use the +[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. - - Next, instantiate an [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). + + Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). ```python from qiskit.primitives import StatevectorEstimator @@ -56,11 +130,10 @@ estimator = StatevectorEstimator() - Next, instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). + Instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). ```python from qiskit.primitives import Estimator - estimator = Estimator() ``` @@ -69,306 +142,420 @@ estimator = Estimator() ### Run and get results -This example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable. +This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one +observable. + +[//]: # (I think that we are going to need a page explaining the V2 broadcasting rules with very very clear examples,) + +[//]: # (so maybe we can keep the example here simple and not try to squeeze in a fast explanation.) -* For V1 primitives, if you want to get expectation values for multiple circuits and observables, you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length. +[//]: # (* For V1 primitives, if you want to get expectation values for multiple circuits and observables, ) -* The V2 primitives accept **vectorized inputs**, where single circuits can be grouped with array-valued specifications. That is, one circuit can be executed - for arrays of `n` parameter sets, `n` observables, or both (in the case of the estimator). Each group is called a **primitive unified bloc (PUB)**, and can be represented as a tuple: `(1 x circuit, [n x observables], [n x parameters])`. Each PUB gets its own result. +[//]: # (you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and ) + +[//]: # (a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length.) + +[//]: # () +[//]: # (* The V2 primitives accept **vectorized inputs**, where single circuits can be grouped with array-valued specifications. That is, one circuit can be executed) + +[//]: # ( for arrays of `n` parameter sets, `n` observables, or both (in the case of the estimator). Each group is called a **primitive unified bloc (PUB)**, and can be represented as a tuple: `(1 x circuit, [n x observables], [n x parameters])`. Each PUB gets its own result.) - - Run the estimation by calling the [`qiskit.primitives.StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method. + + Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) + method, which returns an instance of ... You can get the results from the + job (as an [`qiskit.primitives....Result`](../api/qiskit/qiskit.primitives.EstimatorResult) object) + with the [`qiskit.providers....result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python -job = estimator.run([(qc, observable)]) -result = job.result()[0].data.evs - -print(f" > Metadata: {result[0].metadata}") +job = estimator.run([(qc, observable, parameter_values)]) +result = job.result() +print(f" > Result class: {type(result)}") +``` +```text + (fix) +EstimatorResult(values=array([4.]), metadata=[{}]) ``` - Run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, -which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). + Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, + which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the + job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) + with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - - ```python -job = estimator.run(qc, observable) +```python +job = estimator.run(qc, observable, parameter_values) result = job.result() -print(result) +print(f" > Result class: {type(result)}") ``` -You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) -with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - -```python +```text + (fix) EstimatorResult(values=array([4.]), metadata=[{}]) ``` -#### Get the expected value - +#### Get the expected value from the result - - ```python + + + The primitives V2 result outputs an array of "Pub results". To retrieve the expectation values and metadata for the first + (and in this case, only) circuit evaluation, we must access the evaluation data for pub 0: + +```python print(f" > Expectation value: {result[0].data.evs}") print(f" > Metadata: {result[0].metadata}") +``` +```text +... (fix) +... ``` - From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values). -[`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray` -whose `i`th element is the expectation value corresponding to the `i`th circuit and `i`th observable. + The primitives V1 result stores an array of values that can be accessed through the attribute + [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), to see the values for the first + (and in this case, only) circuit evaluation, we must access the first item of the array: - ```python -exp_value = result.values[0] -print(exp_value) +```python +print(f" > Expectation value: {result.values[0]}") +print(f" > Metadata: {result.metadata}") ``` -```python -3.999999999999999 +```text +... (fix) +... ``` + +[//]: # ( [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray`) + +[//]: # (whose `i`th element is the expectation value corresponding to the `i`th circuit and `i`th observable.) -### Parameterized circuit with `Estimator` -The [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive can be run with unbound parameterized circuits like the one below. -You can also manually bind values to the parameters of the circuit and follow the steps of the previous example. +### Set Estimator run options -```python -from qiskit.circuit import Parameter +By default, the reference Estimator performs an exact statevector calculation based on the +[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. +However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). -theta = Parameter('θ') -param_qc = QuantumCircuit(2) -param_qc.ry(theta, 0) -param_qc.cx(0,1) -print(param_qc.draw(style="iqp")) -``` +With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more precisely defined. +The new interface accepts a `precision` argument that expresses the error bars that the +primitive implementation should target for expectation values estimates, +instead of the number of `shots` used in the V1 interface. -``` - ┌───────┐ -q_0: ┤ Ry(θ) ├──■── - └───────┘┌─┴─┐ -q_1: ─────────┤ X ├ - └───┘ -``` +[//]: # ( The sampling overhead, commonly exposed by V1 implementations) - - - ```python -import numpy as np +[//]: # ( through the `shots` run option, is now an argument of the primitives `run()` method ) -parameter_values = [[0], [np.pi/6], [np.pi/2]] +[//]: # ( that can be specified at the **PUB** level.) -job = estimator.run([(param_qc, [[obs1, obs2, obs3]], [parameter_values])]) +[//]: # ( The V2 base classes expose the arguments in formats different from the V1 API:) -values = job.result()[0].data.evs +[//]: # () +[//]: # ( * [`BaseSamplerV2.run`](/api/qiskit/qiskit.primitives.BaseSamplerV2#run)) -print(f"Parameter: {parameter_values[0]:.5f}\t Expectation value: {result[0].data.evs}") -``` - +[//]: # ( exposes a `shots` argument (similar to the previous workflow):) - - The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. -The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit and observable. +[//]: # ( ) +[//]: # ( ```python) -```python -import numpy as np +[//]: # ( # Sample two circuits at 128 shots each.) -parameter_values = [[0], [np.pi/6], [np.pi/2]] +[//]: # ( sampler_v2.run([circuit1, circuit2], shots=128)) -job = estimator.run([param_qc]*3, [observable]*3, parameter_values=parameter_values) -values = job.result().values +[//]: # ( # Sample two circuits at different amounts of shots. The "None"s are necessary) -for i in range(3): - print(f"Parameter: {parameter_values[i][0]:.5f}\t Expectation value: {values[i]}") -``` +[//]: # ( # as placeholders) -``` -Parameter: 0.00000 Expectation value: 2.0 -Parameter: 0.52360 Expectation value: 3.0 -Parameter: 1.57080 Expectation value: 4.0 -``` - - +[//]: # ( # for the lack of parameter values in this example.) -### Change run options +[//]: # ( sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])) -Your workflow might require tuning primitive run options, such as the number of shots. +[//]: # ( ```) - - The sampling overhead, commonly exposed by V1 implementations - through the `shots` run option, is now an argument of the primitives `run()` method - that can be specified at the **PUB** level. - The V2 base classes expose the arguments in formats different from the V1 API: - - * [`BaseSamplerV2.run`](/api/qiskit/qiskit.primitives.BaseSamplerV2#run) - exposes a `shots` argument (similar to the previous workflow): - - ```python - # Sample two circuits at 128 shots each. - sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) - ``` - - * [`EstimatorV2.run`](/api/qiskit/qiskit.primitives.BaseEstimatorV2#run) - introduces a `precision` argument that specifies the error bars that the - primitive implementation should target for expectation values estimates: - ```python - # Estimate expectation values for two PUBs, both with 0.05 precision. - estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) - ``` - + - - By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact statevector calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be modified to include shot noise if the number of `shots` is set. For reproducibility purposes, a `seed` will also be set in the following examples. + The sampling overhead is now called `precision`, can is defined exclusively at the `.run()` + method level. This allows for a finer grained tuning of the option all the way to the pub level. -There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator): + ```python + # Estimate expectation values for two PUBs, both with 0.05 precision. + estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) + ``` - - Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. - - Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. - -#### Set keyword arguments for [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) + -If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by passing them as keyword arguments. + The V1 interface allowed to specify shots by: + + - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. + - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. - - ```python - # Estimate expectation values for two PUBs, both with 0.05 precision. - estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) - ``` + job = estimator.run(qc, observable, shots=2048, seed=123) + result = job.result() + print(result) + ``` + - - ```python -job = estimator.run(qc, observable, shots=2048, seed=123) -result = job.result() -print(result) -``` -```python -EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) -``` +[//]: # ( By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact ) -```python -print(result.values[0]) -``` +[//]: # ( statevector calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.) -```python -3.999999998697238 -``` - - +[//]: # ( However, this can be modified to include shot noise if the number of `shots` is set.) -#### Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options +[//]: # ( For reproducibility purposes, a `seed` will also be set in the following examples.) -If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. That way you can use the same [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) object as many times as you wish without having to -rewrite the configuration values every time you use [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run). +[//]: # () +[//]: # (There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator):) -#### Modify existing [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) +[//]: # () +[//]: # ( - Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.) -If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments. +[//]: # ( - Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.) -V1 primitives example: +[//]: # (#### Set keyword arguments for [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run)) - - For V2 primitives, `shots` is now an argument of the primitives `run()` method. - +[//]: # () +[//]: # (If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by passing them as keyword arguments.) -```python -estimator.set_options(shots=2048, seed=123) +[//]: # () +[//]: # () -job = estimator.run(qc, observable) -result = job.result() -print(result) -``` +[//]: # ( ) -```python -EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) -``` +[//]: # ( ```python) -```python -print(result.values[0]) -``` +[//]: # ( # Estimate expectation values for two PUBs, both with 0.05 precision.) -```python -3.999999998697238 -``` +[//]: # ( estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)) -#### Define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the options +[//]: # ( ```) -If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, define a `dict` like this one: +[//]: # ( ) +[//]: # () +[//]: # ( ) - - - For V2 primitives, `shots` is an argument of the primitives `run()` method, although you can specify different options, such as `optimization_level`. +[//]: # ( ```python) - **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?** +[//]: # (job = estimator.run(qc, observable, shots=2048, seed=123)) +[//]: # (result = job.result()) - ```python -from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options +[//]: # (print(result)) -service = QiskitRuntimeService() -options = Options() -options.resilience_level = 2 -options.optimization_level = 1 -backend = service.backend("ibmq_qasm_simulator") +[//]: # (```) -estimator = Estimator(options=options, backend=backend) -job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1]) -psi1_H1 = job.result() -``` - +[//]: # () +[//]: # (```python) - - ```python -options = {"shots": 2048, "seed": 123} -``` +[//]: # (EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])) -You can then introduce it into your new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the `options` argument. +[//]: # (```) -```python -estimator = Estimator(options=options) +[//]: # () +[//]: # (```python) -job = estimator.run(qc, observable) -result = job.result() -print(result) -``` +[//]: # (print(result.values[0])) -```python -EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) -``` +[//]: # (```) -```python -print(result.values[0]) -``` +[//]: # () +[//]: # (```python) -```python -3.999999998697238 -``` - - +[//]: # (3.999999998697238) + +[//]: # (```) + +[//]: # ( ) + +[//]: # () + +[//]: # () +[//]: # (#### Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options) + +[//]: # () +[//]: # (If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. That way you can use the same [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) object as many times as you wish without having to) + +[//]: # (rewrite the configuration values every time you use [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run).) + +[//]: # () +[//]: # (#### Modify existing [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator)) + +[//]: # () +[//]: # (If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments.) + +[//]: # () +[//]: # (V1 primitives example: ) + +[//]: # () +[//]: # () + +[//]: # ( For V2 primitives, `shots` is now an argument of the primitives `run()` method.) + +[//]: # ( ) + +[//]: # () +[//]: # (```python) + +[//]: # (estimator.set_options(shots=2048, seed=123)) + +[//]: # () +[//]: # (job = estimator.run(qc, observable)) + +[//]: # (result = job.result()) + +[//]: # (print(result)) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (print(result.values[0])) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (3.999999998697238) + +[//]: # (```) + +[//]: # () +[//]: # (#### Define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the options) + +[//]: # () +[//]: # (If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, define a `dict` like this one:) + +[//]: # () +[//]: # () +[//]: # () -## Compute circuit output probabilities with `Sampler` primitive +[//]: # ( ) -Follow these instructions to get the probability distribution of a quantum circuit with the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive. +[//]: # ( For V2 primitives, `shots` is an argument of the primitives `run()` method, although you can specify different options, such as `optimization_level`.) +[//]: # () +[//]: # ( **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?**) -### Initialize QuantumCircuit +[//]: # () +[//]: # () +[//]: # ( ```python) -The first step is to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s from which you want to obtain the probability distribution. +[//]: # (from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options) + +[//]: # () +[//]: # (service = QiskitRuntimeService()) + +[//]: # (options = Options()) + +[//]: # (options.resilience_level = 2) + +[//]: # (options.optimization_level = 1) + +[//]: # (backend = service.backend("ibmq_qasm_simulator")) + +[//]: # () +[//]: # (estimator = Estimator(options=options, backend=backend)) + +[//]: # (job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1])) + +[//]: # (psi1_H1 = job.result()) + +[//]: # (```) + +[//]: # ( ) + +[//]: # () +[//]: # ( ) + +[//]: # ( ```python) + +[//]: # (options = {"shots": 2048, "seed": 123}) + +[//]: # (```) + +[//]: # () +[//]: # (You can then introduce it into your new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the `options` argument.) + +[//]: # () +[//]: # (```python) + +[//]: # (estimator = Estimator(options=options)) + +[//]: # () +[//]: # (job = estimator.run(qc, observable)) + +[//]: # (result = job.result()) + +[//]: # (print(result)) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (print(result.values[0])) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (3.999999998697238) + +[//]: # (```) + +[//]: # ( ) + +[//]: # () + +## Use the reference `Sampler` + +Similarly to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`: +the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the +[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) +implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization +features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the +legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from +the output probability distributions, but they are expressed in different terms: + +- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or "counts" + for each bitstring present in the output distribution. +- The Sampler (V1) output is always expressed as a "quasi-probability" distribution of output states + +The following code prepares the inputs that will be used in the examples below. Note that +the circuit in the example is parametrized, but you can also run the Sampler on non-parametrized circuits. + +[//]: # (While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), you can sam) + +[//]: # ( ple multiple circuits by passing a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) + +[//]: # ( ) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.) ```python from qiskit import QuantumCircuit @@ -383,16 +570,18 @@ qc.draw("mpl", style="iqp") ![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png "Initial QuantumCircuit") -The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) must include measurements. +Any quantum circuit passed to a Sampler **must** include measurements. ### Initialize `Sampler` -Next, create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance. - +To use the Sampler V2 implementation, follow the instructions to instantiate a +[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain +your pre-existing workflow using a Sampler V1 implementation, you can also use the +[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. - + ```python from qiskit.primitives import StatevectorSampler @@ -411,10 +600,8 @@ sampler = Sampler() ### Run and get results -Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - - + ```python # execute 1 circuit with 3 parameter sets using Sampler V2 job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) @@ -427,33 +614,45 @@ counts = job.result()[0].data.meas.get_counts() ```python # execute 2 circuits with 1 parameter set using Sampler V2 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) +counts1 = job.result() +counts2 = job.result() ``` - ```python -job = sampler.run(qc) -result = job.result() -print(result) -``` + Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) +method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). +You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) +with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. -```python -SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) -``` + ```python + job = sampler.run(qc) + result = job.result() + print(result) + ``` -While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), you can sample multiple circuits by passing a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. + ```python + SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) + ``` ### Get the probability distribution or measurement outcome -From these results you can extract the quasi-probability distributions (V1) with the attribute [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists). The V2 sampler returns measurement outcome samples in the form of **bitstrings** or - **counts**. The bitstrings show the measurement outcomes, preserving the shot - order in which they were measured. The V2 sampler result objects organize - data in terms of their input circuits' classical register names, for - compatibility with dynamic circuits. +As mentioned above, the result retrieval step is different between V1 and V2 interfaces. + +The V1 sampler gives access to quasi-probability distributions. + +The V2 sampler returns measurement outcome samples in the form of **bitstrings** or +**counts**. The bitstrings show the measurement outcomes, preserving the shot +order in which they were measured. The V2 sampler result objects organize +data in terms of their input circuits' classical register names, for +compatibility with dynamic circuits. + +[//]: # ( Even though there is only one circuit in this example, [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists) returns a list of [`qiskit.result.QuasiDistribution`](../api/qiskit/qiskit.result.QuasiDistribution)s.) + +[//]: # (`result.quasi_dists[i]` is the quasi-probability distribution of the `i`th circuit.) + @@ -487,8 +686,6 @@ From these results you can extract the quasi-probability distributions (V1) with - Even though there is only one circuit in this example, [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists) returns a list of [`qiskit.result.QuasiDistribution`](../api/qiskit/qiskit.result.QuasiDistribution)s. -`result.quasi_dists[i]` is the quasi-probability distribution of the `i`th circuit. A quasi-probability distribution differs from a probability distribution in that negative values are also allowed. @@ -513,184 +710,223 @@ Negative quasi-probabilities may appear when using error mitigation techniques. ```text The quasi-probability distribution is: {0: 0.5, 3: 0.5} ``` + + If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. + + ```python + print(quasi_dist.binary_probabilities()) + ``` + + ```python + {'00': 0.4999999999999999, '11': 0.4999999999999999} + ``` + +### Change run options -#### Probability distribution with binary outputs (V1) +By default, the reference Sampler performs an exact statevector calculation based on the +[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. +However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). -If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. +With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined. +The new interface accepts a `shots` argument that can be defined at the "pub level" -```python -print(quasi_dist.binary_probabilities()) -``` + + -```python -{'00': 0.4999999999999999, '11': 0.4999999999999999} -``` + ```python + # Sample two circuits at 128 shots each. + sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) + ``` -### Parameterized circuit with `Sampler` + -The [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive can be run with unbound parameterized circuits like the one below. -You can also manually bind values to the parameters of the circuit and follow the steps of the previous example. + -```python -from qiskit.circuit import Parameter + The V1 interface allowed to specify shots by: -theta = Parameter('θ') -param_qc = QuantumCircuit(2) -param_qc.ry(theta, 0) -param_qc.cx(0,1) -param_qc.measure_all() -print(param_qc.draw(style="iqp")) -``` + - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. + - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. -``` - ┌───────┐ ░ ┌─┐ - q_0: ┤ Ry(θ) ├──■───░─┤M├─── - └───────┘┌─┴─┐ ░ └╥┘┌─┐ - q_1: ─────────┤ X ├─░──╫─┤M├ - └───┘ ░ ║ └╥┘ - meas: 2/══════════════════╩══╩═ - 0 1 -``` + ```python + job = estimator.run(qc, observable, shots=2048, seed=123) + result = job.result() + print(result) + ``` + + +[//]: # (### Change run options) +[//]: # () +[//]: # (Your workflow might require tuning primitive run options, such as the number of shots.) - - - ```python - # run 1 circuit with 3 parameter sets using Sampler V2 - job = sampler_v2.run([(param_qc, parameter_values)]) - result = job.result() - - # Get counts for the classical register "meas" - print(f"Parameter: {parameter_values[0]:.5f}\t Counts: {result[0].data.evs}") - ``` - +[//]: # () +[//]: # (By default, the reference [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class performs an exact statevector) - - The main difference from the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit. +[//]: # (calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be) -```python -import numpy as np +[//]: # (modified to include shot noise if the number of `shots` is set.) -parameter_values = [[0], [np.pi/6], [np.pi/2]] +[//]: # (For reproducibility purposes, a `seed` will also be set in the following examples.) -job = sampler.run([param_qc]*3, parameter_values=parameter_values) -dists = job.result().quasi_dists +[//]: # () +[//]: # (There are two main ways of setting options in the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler):) -for i in range(3): - print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}") -``` +[//]: # () +[//]: # (- Set keyword arguments in the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.) -``` -Parameter: 0.00000 Probabilities: {0: 1.0} -Parameter: 0.52360 Probabilities: {0: 0.9330127018922194, 3: 0.0669872981077807} -Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.4999999999999999} -``` - - +[//]: # (- Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.) +[//]: # () +[//]: # (#### Set keyword arguments for [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)) +[//]: # () +[//]: # (If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by passing them as keyword arguments.) -### Change run options +[//]: # () +[//]: # () +[//]: # () +[//]: # () -Your workflow might require tuning primitive run options, such as the number of shots. +[//]: # ( ) -By default, the reference [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class performs an exact statevector -calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be -modified to include shot noise if the number of `shots` is set. -For reproducibility purposes, a `seed` will also be set in the following examples. +[//]: # ( ```python) -There are two main ways of setting options in the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler): +[//]: # (# Sample two circuits at 128 shots each.) -- Set keyword arguments in the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. -- Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. +[//]: # (sampler_v2.run([circuit1, circuit2], shots=128)) -#### Set keyword arguments for [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) +[//]: # (# Sample two circuits at different amounts of shots. The "None"s are necessary) -If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by passing them as keyword arguments. +[//]: # (# as placeholders) +[//]: # (# for the lack of parameter values in this example.) +[//]: # (sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])) - - - ```python -# Sample two circuits at 128 shots each. -sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) -``` - +[//]: # (```) - - ```python -job = sampler.run(qc, shots=2048, seed=123) -result = job.result() -print(result) -``` +[//]: # ( ) -```python -SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) -``` - - +[//]: # () +[//]: # ( ) -#### Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options +[//]: # ( ```python) -If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run). +[//]: # (job = sampler.run(qc, shots=2048, seed=123)) -#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) (V1) +[//]: # (result = job.result()) -If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use [`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments. +[//]: # (print(result)) -```python -sampler.set_options(shots=2048, seed=123) +[//]: # (```) -job = sampler.run(qc) -result = job.result() -print(result) -``` +[//]: # () +[//]: # (```python) -```python -SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) -``` +[//]: # (SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])) -#### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options +[//]: # (```) -If you prefer, you can define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options. +[//]: # ( ) - - - **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?** - +[//]: # () - - Define a `dict` like this one: +[//]: # () +[//]: # (#### Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options) -```python -options = {"shots": 2048, "seed": 123} -``` +[//]: # () +[//]: # (If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run).) -You can then introduce it into your new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the `options` argument. +[//]: # () +[//]: # (#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) (V1)) -```python -sampler = Sampler(options=options) +[//]: # () +[//]: # (If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use [`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments.) -job = sampler.run(qc) -result = job.result() -print(result) -``` +[//]: # () +[//]: # (```python) -```python -SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) -``` +[//]: # (sampler.set_options(shots=2048, seed=123)) - - +[//]: # () +[//]: # (job = sampler.run(qc)) + +[//]: # (result = job.result()) + +[//]: # (print(result)) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])) + +[//]: # (```) + +[//]: # () +[//]: # (#### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options) + +[//]: # () +[//]: # (If you prefer, you can define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options.) + +[//]: # () +[//]: # () + +[//]: # ( ) + +[//]: # ( **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?**) + +[//]: # ( ) + +[//]: # () +[//]: # ( ) + +[//]: # ( Define a `dict` like this one:) + +[//]: # () +[//]: # (```python) + +[//]: # (options = {"shots": 2048, "seed": 123}) + +[//]: # (```) + +[//]: # () +[//]: # (You can then introduce it into your new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the `options` argument.) + +[//]: # () +[//]: # (```python) + +[//]: # (sampler = Sampler(options=options)) + +[//]: # () +[//]: # (job = sampler.run(qc)) + +[//]: # (result = job.result()) + +[//]: # (print(result)) + +[//]: # (```) + +[//]: # () +[//]: # (```python) + +[//]: # (SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])) + +[//]: # (```) + +[//]: # () +[//]: # ( ) + +[//]: # () ## Next steps From b0592ef387f3c2ce2c4cc981a9491d8d152058d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 4 Apr 2024 18:06:12 +0200 Subject: [PATCH 09/60] Clean up commented-out sections of the document --- .../simulate-with-qiskit-primitives.mdx | 509 +----------------- 1 file changed, 3 insertions(+), 506 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 009658606f2..eb4c4d751a8 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -14,58 +14,6 @@ from output distributions of circuits. The following sections show how to use the reference primitives to run your workflow locally. -[//]: # () -[//]: # () - -[//]: # ( While this guide uses the Qiskit reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). There is not yet an equivalent implementation in V2, but it is coming soon.) - -[//]: # () -[//]: # ( ```python) - -[//]: # ( from qiskit.primitives import BackendEstimator) - -[//]: # ( from import QiskitProvider) - -[//]: # () -[//]: # ( provider = QiskitProvider()) - -[//]: # ( backend = provider.get_backend('backend_name')) - -[//]: # ( estimator = BackendEstimator(backend)) - -[//]: # ( ```) - -[//]: # () -[//]: # ( There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem/#primitives) for more details).) - -[//]: # () - -[//]: # () -[//]: # () - -[//]: # ( While this guide uses the Qiskit reference implementation, the `Sampler` primitive can be run with any provider using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler).) - -[//]: # () -[//]: # ( ```python) - -[//]: # ( from qiskit.primitives import BackendSampler) - -[//]: # ( from import QiskitProvider) - -[//]: # () -[//]: # ( provider = QiskitProvider()) - -[//]: # ( backend = provider.get_backend('backend_name')) - -[//]: # ( sampler = BackendSampler(backend)) - -[//]: # ( ```) - -[//]: # () -[//]: # ( There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details).) - -[//]: # () - ## Use the reference `Estimator` @@ -81,10 +29,6 @@ The following code prepares the inputs that will be used in the examples below. observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits. -[//]: # ( The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s.) - -[//]: # (The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit and observable.) - Any circuit passed to an Estimator must **not** include any **measurements**. @@ -145,20 +89,6 @@ estimator = Estimator() This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one observable. -[//]: # (I think that we are going to need a page explaining the V2 broadcasting rules with very very clear examples,) - -[//]: # (so maybe we can keep the example here simple and not try to squeeze in a fast explanation.) - -[//]: # (* For V1 primitives, if you want to get expectation values for multiple circuits and observables, ) - -[//]: # (you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and ) - -[//]: # (a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length.) - -[//]: # () -[//]: # (* The V2 primitives accept **vectorized inputs**, where single circuits can be grouped with array-valued specifications. That is, one circuit can be executed) - -[//]: # ( for arrays of `n` parameter sets, `n` observables, or both (in the case of the estimator). Each group is called a **primitive unified bloc (PUB)**, and can be represented as a tuple: `(1 x circuit, [n x observables], [n x parameters])`. Each PUB gets its own result.) @@ -241,41 +171,11 @@ By default, the reference Estimator performs an exact statevector calculation ba [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). -With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more precisely defined. +With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined. The new interface accepts a `precision` argument that expresses the error bars that the primitive implementation should target for expectation values estimates, instead of the number of `shots` used in the V1 interface. -[//]: # ( The sampling overhead, commonly exposed by V1 implementations) - -[//]: # ( through the `shots` run option, is now an argument of the primitives `run()` method ) - -[//]: # ( that can be specified at the **PUB** level.) - -[//]: # ( The V2 base classes expose the arguments in formats different from the V1 API:) - -[//]: # () -[//]: # ( * [`BaseSamplerV2.run`](/api/qiskit/qiskit.primitives.BaseSamplerV2#run)) - -[//]: # ( exposes a `shots` argument (similar to the previous workflow):) - -[//]: # ( ) -[//]: # ( ```python) - -[//]: # ( # Sample two circuits at 128 shots each.) - -[//]: # ( sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)])) - -[//]: # ( ```) - @@ -305,235 +205,6 @@ instead of the number of `shots` used in the V1 interface. -[//]: # ( By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact ) - -[//]: # ( statevector calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.) - -[//]: # ( However, this can be modified to include shot noise if the number of `shots` is set.) - -[//]: # ( For reproducibility purposes, a `seed` will also be set in the following examples.) - -[//]: # () -[//]: # (There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator):) - -[//]: # () -[//]: # ( - Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.) - -[//]: # ( - Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.) - -[//]: # (#### Set keyword arguments for [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run)) - -[//]: # () -[//]: # (If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by passing them as keyword arguments.) - -[//]: # () -[//]: # () - -[//]: # ( ) - -[//]: # ( ```python) - -[//]: # ( # Estimate expectation values for two PUBs, both with 0.05 precision.) - -[//]: # ( estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)) - -[//]: # ( ```) - -[//]: # ( ) - -[//]: # () -[//]: # ( ) - -[//]: # ( ```python) - -[//]: # (job = estimator.run(qc, observable, shots=2048, seed=123)) - -[//]: # (result = job.result()) - -[//]: # (print(result)) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (print(result.values[0])) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (3.999999998697238) - -[//]: # (```) - -[//]: # ( ) - -[//]: # () - -[//]: # () -[//]: # (#### Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options) - -[//]: # () -[//]: # (If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. That way you can use the same [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) object as many times as you wish without having to) - -[//]: # (rewrite the configuration values every time you use [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run).) - -[//]: # () -[//]: # (#### Modify existing [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator)) - -[//]: # () -[//]: # (If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments.) - -[//]: # () -[//]: # (V1 primitives example: ) - -[//]: # () -[//]: # () - -[//]: # ( For V2 primitives, `shots` is now an argument of the primitives `run()` method.) - -[//]: # ( ) - -[//]: # () -[//]: # (```python) - -[//]: # (estimator.set_options(shots=2048, seed=123)) - -[//]: # () -[//]: # (job = estimator.run(qc, observable)) - -[//]: # (result = job.result()) - -[//]: # (print(result)) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (print(result.values[0])) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (3.999999998697238) - -[//]: # (```) - -[//]: # () -[//]: # (#### Define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the options) - -[//]: # () -[//]: # (If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, define a `dict` like this one:) - -[//]: # () -[//]: # () -[//]: # () - -[//]: # ( ) - -[//]: # ( For V2 primitives, `shots` is an argument of the primitives `run()` method, although you can specify different options, such as `optimization_level`.) - -[//]: # () -[//]: # ( **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?**) - -[//]: # () -[//]: # () -[//]: # ( ```python) - -[//]: # (from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options) - -[//]: # () -[//]: # (service = QiskitRuntimeService()) - -[//]: # (options = Options()) - -[//]: # (options.resilience_level = 2) - -[//]: # (options.optimization_level = 1) - -[//]: # (backend = service.backend("ibmq_qasm_simulator")) - -[//]: # () -[//]: # (estimator = Estimator(options=options, backend=backend)) - -[//]: # (job = estimator.run(circuits=[psi1], observables=[H1], parameter_values=[theta1])) - -[//]: # (psi1_H1 = job.result()) - -[//]: # (```) - -[//]: # ( ) - -[//]: # () -[//]: # ( ) - -[//]: # ( ```python) - -[//]: # (options = {"shots": 2048, "seed": 123}) - -[//]: # (```) - -[//]: # () -[//]: # (You can then introduce it into your new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the `options` argument.) - -[//]: # () -[//]: # (```python) - -[//]: # (estimator = Estimator(options=options)) - -[//]: # () -[//]: # (job = estimator.run(qc, observable)) - -[//]: # (result = job.result()) - -[//]: # (print(result)) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}])) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (print(result.values[0])) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (3.999999998697238) - -[//]: # (```) - -[//]: # ( ) - -[//]: # () - ## Use the reference `Sampler` Similarly to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`: @@ -549,13 +220,8 @@ the output probability distributions, but they are expressed in different terms: - The Sampler (V1) output is always expressed as a "quasi-probability" distribution of output states The following code prepares the inputs that will be used in the examples below. Note that -the circuit in the example is parametrized, but you can also run the Sampler on non-parametrized circuits. - -[//]: # (While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), you can sam) - -[//]: # ( ple multiple circuits by passing a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) - -[//]: # ( ) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.) +these examples run a single circuit, and the circuit is parametrized, but you can also run the Sampler +on non-parametrized circuits. ```python from qiskit import QuantumCircuit @@ -649,10 +315,6 @@ order in which they were measured. The V2 sampler result objects organize data in terms of their input circuits' classical register names, for compatibility with dynamic circuits. -[//]: # ( Even though there is only one circuit in this example, [`qiskit.primitives.SamplerResult.quasi_dists`](../api/qiskit/qiskit.primitives.SamplerResult#quasi_dists) returns a list of [`qiskit.result.QuasiDistribution`](../api/qiskit/qiskit.result.QuasiDistribution)s.) - -[//]: # (`result.quasi_dists[i]` is the quasi-probability distribution of the `i`th circuit.) - @@ -762,171 +424,6 @@ The new interface accepts a `shots` argument that can be defined at the "pub lev -[//]: # (### Change run options) - -[//]: # () -[//]: # (Your workflow might require tuning primitive run options, such as the number of shots.) - -[//]: # () -[//]: # (By default, the reference [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class performs an exact statevector) - -[//]: # (calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be) - -[//]: # (modified to include shot noise if the number of `shots` is set.) - -[//]: # (For reproducibility purposes, a `seed` will also be set in the following examples.) - -[//]: # () -[//]: # (There are two main ways of setting options in the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler):) - -[//]: # () -[//]: # (- Set keyword arguments in the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.) - -[//]: # (- Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.) - -[//]: # () -[//]: # (#### Set keyword arguments for [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)) - -[//]: # () -[//]: # (If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by passing them as keyword arguments.) - -[//]: # () -[//]: # () -[//]: # () -[//]: # () - -[//]: # ( ) - -[//]: # ( ```python) - -[//]: # (# Sample two circuits at 128 shots each.) - -[//]: # (sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)])) - -[//]: # (```) - -[//]: # ( ) - -[//]: # () -[//]: # ( ) - -[//]: # ( ```python) - -[//]: # (job = sampler.run(qc, shots=2048, seed=123)) - -[//]: # (result = job.result()) - -[//]: # (print(result)) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])) - -[//]: # (```) - -[//]: # ( ) - -[//]: # () - -[//]: # () -[//]: # (#### Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options) - -[//]: # () -[//]: # (If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run).) - -[//]: # () -[//]: # (#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) (V1)) - -[//]: # () -[//]: # (If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use [`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments.) - -[//]: # () -[//]: # (```python) - -[//]: # (sampler.set_options(shots=2048, seed=123)) - -[//]: # () -[//]: # (job = sampler.run(qc)) - -[//]: # (result = job.result()) - -[//]: # (print(result)) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])) - -[//]: # (```) - -[//]: # () -[//]: # (#### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options) - -[//]: # () -[//]: # (If you prefer, you can define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options.) - -[//]: # () -[//]: # () - -[//]: # ( ) - -[//]: # ( **I'M NOT SURE WHAT TO PUT FOR THIS. ARE THERE ANY OPTIONS STILL AVAILABLE FOR V2 BASE PRIMITIVES?**) - -[//]: # ( ) - -[//]: # () -[//]: # ( ) - -[//]: # ( Define a `dict` like this one:) - -[//]: # () -[//]: # (```python) - -[//]: # (options = {"shots": 2048, "seed": 123}) - -[//]: # (```) - -[//]: # () -[//]: # (You can then introduce it into your new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the `options` argument.) - -[//]: # () -[//]: # (```python) - -[//]: # (sampler = Sampler(options=options)) - -[//]: # () -[//]: # (job = sampler.run(qc)) - -[//]: # (result = job.result()) - -[//]: # (print(result)) - -[//]: # (```) - -[//]: # () -[//]: # (```python) - -[//]: # (SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])) - -[//]: # (```) - -[//]: # () -[//]: # ( ) - -[//]: # () ## Next steps From f21db70cc23e1f49a385481afb2c0b002f812294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 4 Apr 2024 18:18:19 +0200 Subject: [PATCH 10/60] Address previous review comments --- .../simulate-with-qiskit-primitives.mdx | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index eb4c4d751a8..2962e833329 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -53,7 +53,7 @@ import numpy as np theta_values = [[0], [np.pi/6], [np.pi/2]] ``` -Note: fix circuit image (doesn't correspond to code) +TODO: fix circuit image (doesn't correspond to code) ![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png "Initial QuantumCircuit") ### Initialize an Estimator @@ -94,8 +94,8 @@ observable. Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method, which returns an instance of ... You can get the results from the - job (as an [`qiskit.primitives....Result`](../api/qiskit/qiskit.primitives.EstimatorResult) object) - with the [`qiskit.providers....result`](../api/qiskit/qiskit.providers.JobV1#result) method. + job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) + with the [`qiskit.primitives.PrimitiveResult.result`](../api/qiskit/qiskit.primitives.PrimitiveResult#result) method. ```python job = estimator.run([(qc, observable, parameter_values)]) @@ -103,7 +103,7 @@ result = job.result() print(f" > Result class: {type(result)}") ``` ```text - (fix) +... (TODO:add output) EstimatorResult(values=array([4.]), metadata=[{}]) ``` @@ -119,7 +119,7 @@ result = job.result() print(f" > Result class: {type(result)}") ``` ```text - (fix) +... (TODO:add output) EstimatorResult(values=array([4.]), metadata=[{}]) ``` @@ -130,23 +130,26 @@ EstimatorResult(values=array([4.]), metadata=[{}]) - The primitives V2 result outputs an array of "Pub results". To retrieve the expectation values and metadata for the first - (and in this case, only) circuit evaluation, we must access the evaluation data for pub 0: + The primitives V2 result outputs an array of `PubResult`s, where each item of the array is a `PubResult` object + that contains in its data the array of evaluations corresponding to every circuit-observable combination in the Pub. + To retrieve the expectation values and metadata for the first + (and in this case, only) circuit evaluation, we must access the evaluation `data` for pub 0: ```python print(f" > Expectation value: {result[0].data.evs}") print(f" > Metadata: {result[0].metadata}") ``` ```text -... (fix) +... (TODO:add output) ... ``` The primitives V1 result stores an array of values that can be accessed through the attribute - [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), to see the values for the first - (and in this case, only) circuit evaluation, we must access the first item of the array: + [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th + element is the expectation value corresponding to the `i`th circuit and `i`th observable. + To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array. ```python print(f" > Expectation value: {result.values[0]}") @@ -154,13 +157,9 @@ print(f" > Metadata: {result.metadata}") ``` ```text -... (fix) +... (TODO:add output) ... ``` - -[//]: # ( [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray`) - -[//]: # (whose `i`th element is the expectation value corresponding to the `i`th circuit and `i`th observable.) @@ -269,27 +268,27 @@ sampler = Sampler() ```python -# execute 1 circuit with 3 parameter sets using Sampler V2 -job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) -counts = job.result()[0].data.meas.get_counts() -``` - V2 primitives accept multiple PUBs as inputs, and each pub gets its own result. This + # execute 1 circuit with 3 parameter sets using Sampler V2 + job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) + counts = job.result()[0].data.meas.get_counts() + ``` + V2 primitives accept multiple PUBs as inputs, and each pub gets its own result. This lets you run different circuits with various parameter/observable combinations, which was not always possible in the V1 interface: -```python -# execute 2 circuits with 1 parameter set using Sampler V2 -job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)]) -counts1 = job.result() -counts2 = job.result() -``` + ```python + # execute 2 circuits with 1 parameter set using Sampler V2 + job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)]) + counts1 = job.result() + counts2 = job.result() + ``` Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) -method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). -You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) -with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. + method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). + You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) + with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python job = sampler.run(qc) From 19f384d3f9c06a65c9c87b948fef46ee7979da54 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 13:59:53 -0400 Subject: [PATCH 11/60] no longer need tm for Qiskit --- docs/run/primitives-get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/run/primitives-get-started.mdx b/docs/run/primitives-get-started.mdx index 91915bfbc81..9139d4d9ff7 100644 --- a/docs/run/primitives-get-started.mdx +++ b/docs/run/primitives-get-started.mdx @@ -20,7 +20,7 @@ service = QiskitRuntimeService(channel="ibm_cloud", channel_strategy="q-ctrl") - While this documentation uses the primitives from Qiskit® Runtime, which allow you to use IBM® backends, the primitives can be run on any provider by using the [backend primitives](#backend) instead. Additionally, you can use the *reference* primitives to run on a local statevector simulator. See [Exact simulation with Qiskit primitives](../verify/simulate-with-qiskit-primitives) for details. + While this documentation uses the primitives from Qiskit Runtime, which allow you to use IBM® backends, the primitives can be run on any provider by using the [backend primitives](#backend) instead. Additionally, you can use the *reference* primitives to run on a local statevector simulator. See [Exact simulation with Qiskit primitives](../verify/simulate-with-qiskit-primitives) for details. From 6d63ad6f7f0eea2850a197b68d72ea7128e65cac Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:01:18 -0400 Subject: [PATCH 12/60] simplify --- docs/run/primitives-get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/run/primitives-get-started.mdx b/docs/run/primitives-get-started.mdx index 9139d4d9ff7..ba771bca467 100644 --- a/docs/run/primitives-get-started.mdx +++ b/docs/run/primitives-get-started.mdx @@ -237,7 +237,7 @@ print(f" > Metadata: {result.metadata[0]}") ## Get started with the backend primitives -The `Sampler` primitive can be run with any provider by using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). Likewise, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). There are not yet equivalent implementations in V2, but they are coming soon. +The `Sampler` primitive can be run with any provider by using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). Likewise, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). Equivalent implementations in V2 are coming soon. There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details). From 129a71e4257086497a775ad9d1f0a7516bad50bf Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:01:57 -0400 Subject: [PATCH 13/60] simplify --- docs/run/primitives-get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/run/primitives-get-started.mdx b/docs/run/primitives-get-started.mdx index ba771bca467..ff19eb0bfcb 100644 --- a/docs/run/primitives-get-started.mdx +++ b/docs/run/primitives-get-started.mdx @@ -239,7 +239,7 @@ print(f" > Metadata: {result.metadata[0]}") The `Sampler` primitive can be run with any provider by using [`qiskit.primitives.BackendSampler`](../api/qiskit/qiskit.primitives.BackendSampler). Likewise, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). Equivalent implementations in V2 are coming soon. -There are some providers that implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details). +Some providers implement primitives natively (see [the Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#providers) for more details). ### Example: BackendEstimator From 8425dd730ae734a584839acf53e735943c7f5610 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:02:51 -0400 Subject: [PATCH 14/60] new guidance: no need to tm Qiskit --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 2962e833329..ebbc26bc392 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -5,7 +5,7 @@ description: How to perform exact simulation of quantum circuits using primitive # Exact simulation with Qiskit primitives -The reference primitives in Qiskit® perform local statevector simulations. These simulations do not support +The reference primitives in Qiskit perform local statevector simulations. These simulations do not support modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives). From be01d9c2b9e9e0c26e5955792858209f6ef426a3 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:05:50 -0400 Subject: [PATCH 15/60] tweaks --- docs/verify/simulate-with-qiskit-primitives.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index ebbc26bc392..63b1d41f83a 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -18,11 +18,11 @@ The following sections show how to use the reference primitives to run your work ## Use the reference `Estimator` There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector -simulators, the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the +simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) -implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization +implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the -legacy Estimator V1 interface. Both can take circuits, observables and parameters as inputs and return the locally +legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally computed expectation values. The following code prepares the inputs that will be used in the examples below. The expected input type for the From 158f0be5fb1e2564ab8d0c0695a8e55647a21dc4 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:07:34 -0400 Subject: [PATCH 16/60] avoid "below" --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 63b1d41f83a..926f45979f4 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -25,7 +25,7 @@ features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Es legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally computed expectation values. -The following code prepares the inputs that will be used in the examples below. The expected input type for the +The following code prepares the inputs that will be used in the examples that follow. The expected input type for the observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits. From f99c45c2bb3d70df855ee2a30576ee1211bdb3ef Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:09:57 -0400 Subject: [PATCH 17/60] typo and tweak --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 926f45979f4..2325b8147a1 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -178,8 +178,8 @@ instead of the number of `shots` used in the V1 interface. - The sampling overhead is now called `precision`, can is defined exclusively at the `.run()` - method level. This allows for a finer grained tuning of the option all the way to the pub level. + The sampling overhead is now called `precision`, and is defined exclusively at the `.run()` + method level. This allows for a more finely-grained tuning of the option all the way to the pub level. ```python # Estimate expectation values for two PUBs, both with 0.05 precision. From d8cfb0e29b8ed7c7e6333c3d6b13dd3d2a6cedbc Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:11:15 -0400 Subject: [PATCH 18/60] rmv sentence fragment --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 2325b8147a1..209807523af 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -190,7 +190,7 @@ instead of the number of `shots` used in the V1 interface. - The V1 interface allowed to specify shots by: + The V1 interface specifies shots in the following ways: - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. From 9bd026d8019589007ec95625e6afcef83f10bd5e Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:12:46 -0400 Subject: [PATCH 19/60] Update docs/verify/simulate-with-qiskit-primitives.mdx --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 209807523af..7cbd463fb7b 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -216,7 +216,7 @@ the output probability distributions, but they are expressed in different terms: - The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or "counts" for each bitstring present in the output distribution. -- The Sampler (V1) output is always expressed as a "quasi-probability" distribution of output states +- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states. The following code prepares the inputs that will be used in the examples below. Note that these examples run a single circuit, and the circuit is parametrized, but you can also run the Sampler From 339eb2cb95b03dd68c0d6bfb4e0a41fa5d4f146a Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:14:12 -0400 Subject: [PATCH 20/60] simplify --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 7cbd463fb7b..5277bd89030 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -218,8 +218,8 @@ the output probability distributions, but they are expressed in different terms: for each bitstring present in the output distribution. - The Sampler (V1) output is always expressed as a quasi-probability distribution of output states. -The following code prepares the inputs that will be used in the examples below. Note that -these examples run a single circuit, and the circuit is parametrized, but you can also run the Sampler +The following code prepares the inputs used in the examples that follow. Note that +these examples run a single parametrized circuit, but you can also run the Sampler on non-parametrized circuits. ```python From 84f9e48f2b29e211a02af01b6a697e933f8a6532 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:18:04 -0400 Subject: [PATCH 21/60] tweaks --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 5277bd89030..796cbfe3c92 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -272,8 +272,8 @@ sampler = Sampler() job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) counts = job.result()[0].data.meas.get_counts() ``` - V2 primitives accept multiple PUBs as inputs, and each pub gets its own result. This - lets you run different circuits with various parameter/observable combinations, + V2 primitives accept multiple pubs as inputs, and each pub gets its own result. + Therefore, you can run different circuits with various parameter/observable combinations, which was not always possible in the V1 interface: ```python From e2da48ab4f30d0d99c81d134390447fe0a1d15d9 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:19:45 -0400 Subject: [PATCH 22/60] missing period --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 796cbfe3c92..f944da74bd3 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -392,7 +392,7 @@ By default, the reference Sampler performs an exact statevector calculation base However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined. -The new interface accepts a `shots` argument that can be defined at the "pub level" +The new interface accepts a `shots` argument that can be defined at the "pub level". From 83da6060bceae9e521dc941b797b8bd2117a0d75 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 4 Apr 2024 14:20:59 -0400 Subject: [PATCH 23/60] wordsmith --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f944da74bd3..8c54e607da1 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -410,7 +410,7 @@ The new interface accepts a `shots` argument that can be defined at the "pub lev - The V1 interface allowed to specify shots by: + The V1 interface specifies shots in the following ways: - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. From 58bf43c3caaf309df33aebe5fd0032e10b6df886 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 4 Apr 2024 14:25:26 -0400 Subject: [PATCH 24/60] PUB rather than pub --- docs/verify/simulate-with-qiskit-primitives.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 8c54e607da1..f97b7208013 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -133,7 +133,7 @@ EstimatorResult(values=array([4.]), metadata=[{}]) The primitives V2 result outputs an array of `PubResult`s, where each item of the array is a `PubResult` object that contains in its data the array of evaluations corresponding to every circuit-observable combination in the Pub. To retrieve the expectation values and metadata for the first - (and in this case, only) circuit evaluation, we must access the evaluation `data` for pub 0: + (and in this case, only) circuit evaluation, we must access the evaluation `data` for PUB 0: ```python print(f" > Expectation value: {result[0].data.evs}") @@ -179,7 +179,7 @@ instead of the number of `shots` used in the V1 interface. The sampling overhead is now called `precision`, and is defined exclusively at the `.run()` - method level. This allows for a more finely-grained tuning of the option all the way to the pub level. + method level. This allows for a more finely-grained tuning of the option all the way to the PUB level. ```python # Estimate expectation values for two PUBs, both with 0.05 precision. @@ -272,7 +272,7 @@ sampler = Sampler() job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) counts = job.result()[0].data.meas.get_counts() ``` - V2 primitives accept multiple pubs as inputs, and each pub gets its own result. + V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result. Therefore, you can run different circuits with various parameter/observable combinations, which was not always possible in the V1 interface: @@ -331,7 +331,7 @@ compatibility with dynamic circuits. ```python # Run using V2 sampler result = sampler_v2.run([circuit]).result() - # Access result data for pub 0 + # Access result data for PUB 0 data_pub = result[0].data # Access bitstring for the classical register "meas" bitstring = data_pub.meas.get_bitstring() @@ -392,7 +392,7 @@ By default, the reference Sampler performs an exact statevector calculation base However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined. -The new interface accepts a `shots` argument that can be defined at the "pub level". +The new interface accepts a `shots` argument that can be defined at the "PUB level". From 82e806a152699fe07fde23ea0bbd7f67c7640cca Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 4 Apr 2024 14:29:07 -0400 Subject: [PATCH 25/60] fix broken internal link --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f97b7208013..e4d734b04b7 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -95,7 +95,7 @@ observable. Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method, which returns an instance of ... You can get the results from the job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) - with the [`qiskit.primitives.PrimitiveResult.result`](../api/qiskit/qiskit.primitives.PrimitiveResult#result) method. + with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method. ```python job = estimator.run([(qc, observable, parameter_values)]) From 94179671ea41edd79ea50e74e1f2582bc16268e8 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:04:58 -0400 Subject: [PATCH 26/60] convert to notebook --- ...ELETE-simulate-with-qiskit-primitives.mdx} | 0 .../simulate-with-qiskit-primitives.ipynb | 555 ++++++++++++++++++ 2 files changed, 555 insertions(+) rename docs/verify/{simulate-with-qiskit-primitives.mdx => DELETE-simulate-with-qiskit-primitives.mdx} (100%) create mode 100644 docs/verify/simulate-with-qiskit-primitives.ipynb diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/DELETE-simulate-with-qiskit-primitives.mdx similarity index 100% rename from docs/verify/simulate-with-qiskit-primitives.mdx rename to docs/verify/DELETE-simulate-with-qiskit-primitives.mdx diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb new file mode 100644 index 00000000000..1c07d875dca --- /dev/null +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -0,0 +1,555 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exact simulation with Qiskit primitives" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", + "modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation\n", + "techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives).\n", + "\n", + "The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample\n", + "from output distributions of circuits.\n", + "\n", + "The following sections show how to use the reference primitives to run your workflow locally." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector\n", + "simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the\n", + "[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator)\n", + "implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization\n", + "features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the\n", + "legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally\n", + "computed expectation values.\n", + "\n", + "The following code prepares the inputs that will be used in the examples that follow. The expected input type for the\n", + "observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that\n", + "the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits.\n", + "\n", + "\n", + " Any circuit passed to an Estimator must **not** include any **measurements**.\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "from qiskit.circuit import Parameter\n", + "from qiskit.quantum_info import SparsePauliOp\n", + "\n", + "# circuit for which you want to obtain the expected value\n", + "qc = QuantumCircuit(2)\n", + "qc.ry(Parameter('theta'), 0)\n", + "qc.h(0)\n", + "qc.cx(0,1)\n", + "qc.draw(\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# observable(s) whose expected values you want to compute\n", + "observable = SparsePauliOp([\"II\", \"XX\", \"YY\", \"ZZ\"], coeffs=[1, 1, -1, 1])\n", + "\n", + "# value(s) for the circuit parameter(s)\n", + "import numpy as np\n", + "parameter_values = [[0], [np.pi/6], [np.pi/2]]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize an Estimator\n", + "\n", + "To use the Estimator V2 implementation, follow the instructions to instantiate a\n", + "[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain\n", + "your pre-existing workflow using an Estimator V1 implementation, you can also use the\n", + "[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class.\n", + "\n", + "\n", + " \n", + " Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator).\n", + "\n", + "```python\n", + "from qiskit.primitives import StatevectorEstimator\n", + "estimator = StatevectorEstimator()\n", + "```\n", + " \n", + "\n", + " \n", + " Instantiate a [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator).\n", + "\n", + "```python\n", + "from qiskit.primitives import Estimator\n", + "estimator = Estimator()\n", + "```\n", + " \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run and get results\n", + "\n", + "This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one\n", + "observable.\n", + "\n", + "\n", + "\n", + " \n", + " Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run)\n", + " method, which returns an instance of a [PrimitiveJob](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the\n", + " job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object)\n", + " with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method.\n", + "\n", + "```python\n", + "job = estimator.run([(qc, observable, parameter_values)])\n", + "result = job.result()\n", + "print(f\" > Result class: {type(result)}\")\n", + "```\n", + "```text\n", + " > Result class: \n", + "```\n", + " \n", + " \n", + " Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method,\n", + " which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the\n", + " job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object)\n", + " with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", + "\n", + "```python\n", + "job = estimator.run([qc]*3, [observable]*3, parameter_values)\n", + "result = job.result()\n", + "print(f\" > Result class: {type(result)}\")\n", + "```\n", + "```text\n", + " > Result class: \n", + "```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Get the expected value from the result\n", + "\n", + "\n", + " \n", + "\n", + " The primitives V2 result outputs an array of [`PubResult`s](/api/qiskit/qiskit.primitives.PubResult#pubresult), where each item of the array is a `PubResult` object\n", + " that contains in its data the array of evaluations corresponding to every circuit-observable combination in the PUB.\n", + " To retrieve the expectation values and metadata for the first\n", + " (and in this case, only) circuit evaluation, we must access the evaluation [`data`](/api/qiskit/qiskit.primitives.PubResult#data) for PUB 0:\n", + "\n", + "```python\n", + "print(f\" > Expectation value: {result[0].data.evs}\")\n", + "print(f\" > Metadata: {result[0].metadata}\")\n", + "```\n", + "```text\n", + " > Expectation value: [4. 3.73205081 2. ]\n", + " > Metadata: {'precision': 0.0}\n", + "```\n", + " \n", + " \n", + "\n", + " The primitives V1 result stores an array of values that can be accessed through the attribute\n", + " [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th\n", + " element is the expectation value corresponding to the `i`th circuit and `i`th observable.\n", + " To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array.\n", + "\n", + "```python\n", + "print(f\" > Expectation value: {result.values[0]}\")\n", + "print(f\" > Metadata: {result.metadata}\")\n", + "```\n", + "\n", + "```text\n", + " > Expectation value: 3.999999999999999\n", + " > Metadata: [{}, {}, {}]\n", + "```\n", + " \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set Estimator run options\n", + "\n", + "By default, the reference Estimator performs an exact statevector calculation based on the\n", + "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", + "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", + "\n", + "With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined.\n", + "The new interface accepts a `precision` argument that expresses the error bars that the\n", + "primitive implementation should target for expectation values estimates,\n", + "instead of the number of `shots` used in the V1 interface.\n", + "\n", + "\n", + " \n", + "\n", + " The sampling overhead is now called `precision`, and is defined exclusively at the `.run()`\n", + " method level. This allows for a more finely-grained tuning of the option all the way to the PUB level.\n", + "\n", + " ```python\n", + " # Estimate expectation values for two PUBs, both with 0.05 precision.\n", + " estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)\n", + " ```\n", + "\n", + " \n", + "\n", + " \n", + "\n", + " The V1 interface specifies shots in the following ways:\n", + "\n", + " - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.\n", + " - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.\n", + "\n", + " ```python\n", + " job = estimator.run(qc, observable, shots=2048, seed=123)\n", + " result = job.result()\n", + " print(result)\n", + " ```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use the reference `Sampler`\n", + "\n", + "Similarly to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`:\n", + "the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the\n", + "[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler)\n", + "implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization\n", + "features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the\n", + "legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from\n", + "the output probability distributions, but they are expressed in different terms:\n", + "\n", + "- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or \"counts\"\n", + " for each bitstring present in the output distribution.\n", + "- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states.\n", + "\n", + "The following code prepares the inputs used in the examples that follow. Note that\n", + "these examples run a single parametrized circuit, but you can also run the Sampler\n", + "on non-parametrized circuits." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "\n", + "qc = QuantumCircuit(2)\n", + "qc.h(0)\n", + "qc.cx(0,1)\n", + "qc.measure_all()\n", + "qc.draw(\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Any quantum circuit passed to a Sampler **must** include measurements.\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize `Sampler`\n", + "\n", + "To use the Sampler V2 implementation, follow the instructions to instantiate a\n", + "[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain\n", + "your pre-existing workflow using a Sampler V1 implementation, you can also use the\n", + "[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class.\n", + "\n", + "\n", + " \n", + " ```python\n", + "from qiskit.primitives import StatevectorSampler\n", + "\n", + "sampler = StatevectorSampler()\n", + "```\n", + " \n", + "\n", + " \n", + " ```python\n", + "from qiskit.primitives import Sampler\n", + "\n", + "sampler = Sampler()\n", + "```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run and get results\n", + "\n", + "\n", + " \n", + " ```python\n", + " # execute 1 circuit with 3 parameter sets using Sampler V2\n", + " job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])\n", + " counts = job.result()[0].data.meas.get_counts()\n", + " ```\n", + " V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result.\n", + " Therefore, you can run different circuits with various parameter/observable combinations,\n", + " which was not always possible in the V1 interface:\n", + "\n", + " ```python\n", + " # execute 2 circuits with 1 parameter set using Sampler V2\n", + " job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])\n", + " counts1 = job.result()\n", + " counts2 = job.result()\n", + " ```\n", + " \n", + "\n", + " \n", + " Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)\n", + " method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1).\n", + " You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object)\n", + " with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", + "\n", + " ```python\n", + " job = sampler.run(qc)\n", + " result = job.result()\n", + " print(result)\n", + " ```\n", + "\n", + " ```python\n", + " SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}])\n", + " ```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get the probability distribution or measurement outcome\n", + "\n", + "As mentioned above, the result retrieval step is different between V1 and V2 interfaces.\n", + "\n", + "The V1 sampler gives access to quasi-probability distributions.\n", + "\n", + "The V2 sampler returns measurement outcome samples in the form of **bitstrings** or\n", + "**counts**. The bitstrings show the measurement outcomes, preserving the shot\n", + "order in which they were measured. The V2 sampler result objects organize\n", + "data in terms of their input circuits' classical register names, for\n", + "compatibility with dynamic circuits.\n", + "\n", + "\n", + "\n", + " \n", + " The name of the classical register defaults to `\"meas\"`.\n", + " This name will be used later to access the measurement bitstrings.\n", + "\n", + " ```python\n", + " # Define quantum circuit with 2 qubits\n", + " circuit = QuantumCircuit(2)\n", + " circuit.h(0)\n", + " circuit.cx(0, 1)\n", + " circuit.measure_all()\n", + " circuit.draw()\n", + " ```\n", + " ```python\n", + " # Run using V2 sampler\n", + " result = sampler_v2.run([circuit]).result()\n", + " # Access result data for PUB 0\n", + " data_pub = result[0].data\n", + " # Access bitstring for the classical register \"meas\"\n", + " bitstring = data_pub.meas.get_bitstring()\n", + " print(f\"The bitstring shape is: {bitstring.shape}\")\n", + " # Get counts for the classical register \"meas\"\n", + " counts = data_pub.meas.get_counts()\n", + " print(f\"The counts are: {counts}\")\n", + " ```\n", + " ```text\n", + " The bitstring shape is: (1024, 1)\n", + " The counts are: {'00': 523, '11': 501}\n", + " ```\n", + " \n", + "\n", + " \n", + "\n", + "\n", + "A quasi-probability distribution differs from a probability distribution in that negative values are also allowed.\n", + "However, the quasi-probabilities must sum up to 1 like probabilities.\n", + "Negative quasi-probabilities may appear when using error mitigation techniques.\n", + "\n", + " ```python\n", + " # Define quantum circuit with 2 qubits\n", + " circuit = QuantumCircuit(2)\n", + " circuit.h(0)\n", + " circuit.cx(0, 1)\n", + " circuit.measure_all()\n", + " circuit.draw()\n", + " ```\n", + "\n", + " ```python\n", + " # Run using V1 sampler\n", + " result = sampler_v1.run(circuit).result()\n", + " quasi_dist = result.quasi_dists[0]\n", + " print(f\"The quasi-probability distribution is: {quasi_dist}\")\n", + " ```\n", + " ```text\n", + " The quasi-probability distribution is: {0: 0.5, 3: 0.5}\n", + " ```\n", + "\n", + " If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method.\n", + "\n", + " ```python\n", + " print(quasi_dist.binary_probabilities())\n", + " ```\n", + "\n", + " ```python\n", + " {'00': 0.4999999999999999, '11': 0.4999999999999999}\n", + " ```\n", + "\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Change run options\n", + "\n", + "By default, the reference Sampler performs an exact statevector calculation based on the\n", + "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", + "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", + "\n", + "With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined.\n", + "The new interface accepts a `shots` argument that can be defined at the \"PUB level\".\n", + "\n", + "\n", + " \n", + "\n", + " ```python\n", + " # Sample two circuits at 128 shots each.\n", + " sampler_v2.run([circuit1, circuit2], shots=128)\n", + " # Sample two circuits at different amounts of shots. The \"None\"s are necessary\n", + " # as placeholders\n", + " # for the lack of parameter values in this example.\n", + " sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])\n", + " ```\n", + "\n", + " \n", + "\n", + " \n", + "\n", + " The V1 interface specifies shots in the following ways:\n", + "\n", + " - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.\n", + " - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.\n", + "\n", + " ```python\n", + " job = estimator.run(qc, observable, shots=2048, seed=123)\n", + " result = job.result()\n", + " print(result)\n", + " ```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next steps\n", + "\n", + "\n", + " - For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer).\n", + " - To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial.\n", + " - Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference.\n", + " - Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference.\n", + " - Learn how to run on a physical system in the [Run](../run) section.\n", + "" + ] + } + ], + "metadata": { + "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + }, + "title": "Exact simulation with Qiskit primitives" + }, + "nbformat": 4, + "nbformat_minor": 4 +} From b5dd11d91c04070867a61daf759a201c62650d87 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:15:49 -0400 Subject: [PATCH 27/60] tox --- .../simulate-with-qiskit-primitives.ipynb | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb index 1c07d875dca..11744d72d7d 100644 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "d2df2a32-dca3-4da8-9786-488203bd063b", "metadata": {}, "source": [ "# Exact simulation with Qiskit primitives" @@ -9,6 +10,7 @@ }, { "cell_type": "markdown", + "id": "c623b6f4-cbb8-4ec2-9db2-8f867a117740", "metadata": {}, "source": [ "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", @@ -23,6 +25,7 @@ }, { "cell_type": "markdown", + "id": "8366190d-e993-4b26-9d68-a6c1157be489", "metadata": {}, "source": [ "There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector\n", @@ -45,6 +48,7 @@ { "cell_type": "code", "execution_count": 1, + "id": "f129715c-80d1-4ecb-acb2-ef6f1fd14fa6", "metadata": {}, "outputs": [ { @@ -75,6 +79,7 @@ { "cell_type": "code", "execution_count": 2, + "id": "ed97b688-03b2-4b40-be95-dbd386e440b0", "metadata": {}, "outputs": [], "source": [ @@ -88,6 +93,7 @@ }, { "cell_type": "markdown", + "id": "23f43e76-7af2-430b-afa3-3fe8ba982aab", "metadata": {}, "source": [ "### Initialize an Estimator\n", @@ -115,11 +121,12 @@ "estimator = Estimator()\n", "```\n", " \n", - "\n" + "" ] }, { "cell_type": "markdown", + "id": "0afa247f-7b6d-4c4a-b543-934747eb0016", "metadata": {}, "source": [ "### Run and get results\n", @@ -164,6 +171,7 @@ }, { "cell_type": "markdown", + "id": "06beb167-00d9-43e0-837e-09660471a9f3", "metadata": {}, "source": [ "#### Get the expected value from the result\n", @@ -202,11 +210,12 @@ " > Metadata: [{}, {}, {}]\n", "```\n", " \n", - "\n" + "" ] }, { "cell_type": "markdown", + "id": "e327b0ab-2bf5-40c1-ae86-70b1a3f7f2ea", "metadata": {}, "source": [ "### Set Estimator run options\n", @@ -251,6 +260,7 @@ }, { "cell_type": "markdown", + "id": "9ae0d76a-0e99-413f-b370-b09cf2eec844", "metadata": {}, "source": [ "## Use the reference `Sampler`\n", @@ -275,6 +285,7 @@ { "cell_type": "code", "execution_count": 5, + "id": "711c6bff-3d48-4035-8b67-f789834dbbda", "metadata": {}, "outputs": [ { @@ -301,6 +312,7 @@ }, { "cell_type": "markdown", + "id": "470ed0fb-3481-4203-91c6-0a192270e0e0", "metadata": {}, "source": [ "\n", @@ -310,6 +322,7 @@ }, { "cell_type": "markdown", + "id": "f8a14653-f2ca-4943-83a6-4a9621015d31", "metadata": {}, "source": [ "### Initialize `Sampler`\n", @@ -340,6 +353,7 @@ }, { "cell_type": "markdown", + "id": "2dd4fd9e-8e6a-4371-a135-bd4ff9a341b2", "metadata": {}, "source": [ "### Run and get results\n", @@ -384,6 +398,7 @@ }, { "cell_type": "markdown", + "id": "fc701e56-2bc9-49aa-ada6-103a23ef0fbe", "metadata": {}, "source": [ "### Get the probability distribution or measurement outcome\n", @@ -472,6 +487,7 @@ }, { "cell_type": "markdown", + "id": "164ebfeb-9f7e-4cff-96e6-02b7e1eb7dbd", "metadata": {}, "source": [ "### Change run options\n", @@ -515,6 +531,7 @@ }, { "cell_type": "markdown", + "id": "1c1e8c2d-90df-4d24-bce7-491ad18b75b8", "metadata": {}, "source": [ "## Next steps\n", @@ -532,7 +549,7 @@ "metadata": { "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -546,7 +563,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3" }, "title": "Exact simulation with Qiskit primitives" }, From d41ebcdfa13b779dfac4dc0febda147ac64daf0e Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:20:39 -0400 Subject: [PATCH 28/60] missing header --- docs/verify/simulate-with-qiskit-primitives.ipynb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb index 11744d72d7d..bfec642ce45 100644 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -28,6 +28,8 @@ "id": "8366190d-e993-4b26-9d68-a6c1157be489", "metadata": {}, "source": [ + "## Use the reference `Estimator`\n", + "\n", "There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector\n", "simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the\n", "[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator)\n", @@ -265,7 +267,7 @@ "source": [ "## Use the reference `Sampler`\n", "\n", - "Similarly to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`:\n", + "Similar to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`:\n", "the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the\n", "[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler)\n", "implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization\n", From 89f1cd19dbc9a6caa04305fd570b85a53cfb4d3a Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:22:08 -0400 Subject: [PATCH 29/60] Delete DELETE-simulate-with-qiskit-primitives.mdx --- ...DELETE-simulate-with-qiskit-primitives.mdx | 435 ------------------ 1 file changed, 435 deletions(-) delete mode 100644 docs/verify/DELETE-simulate-with-qiskit-primitives.mdx diff --git a/docs/verify/DELETE-simulate-with-qiskit-primitives.mdx b/docs/verify/DELETE-simulate-with-qiskit-primitives.mdx deleted file mode 100644 index e4d734b04b7..00000000000 --- a/docs/verify/DELETE-simulate-with-qiskit-primitives.mdx +++ /dev/null @@ -1,435 +0,0 @@ ---- -title: Exact simulation with Qiskit primitives -description: How to perform exact simulation of quantum circuits using primitives in Qiskit. ---- - -# Exact simulation with Qiskit primitives - -The reference primitives in Qiskit perform local statevector simulations. These simulations do not support -modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation -techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives). - -The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample -from output distributions of circuits. - -The following sections show how to use the reference primitives to run your workflow locally. - - -## Use the reference `Estimator` - -There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector -simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the -[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) -implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization -features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the -legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally -computed expectation values. - -The following code prepares the inputs that will be used in the examples that follow. The expected input type for the -observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that -the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits. - - - Any circuit passed to an Estimator must **not** include any **measurements**. - - -```python -from qiskit import QuantumCircuit -from qiskit.circuit import Parameter -from qiskit.quantum_info import SparsePauliOp - -# circuit for which you want to obtain the expected value -qc = QuantumCircuit(2) -qc.ry(Parameter('theta'), 0) -qc.h(0) -qc.cx(0,1) -qc.draw("mpl", style="iqp") - -# observable(s) whose expected values you want to compute -observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) - -# value(s) for the circuit parameter(s) -import numpy as np -theta_values = [[0], [np.pi/6], [np.pi/2]] -``` - -TODO: fix circuit image (doesn't correspond to code) -![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png "Initial QuantumCircuit") - -### Initialize an Estimator - -To use the Estimator V2 implementation, follow the instructions to instantiate a -[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain -your pre-existing workflow using an Estimator V1 implementation, you can also use the -[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. - - - - Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). - -```python -from qiskit.primitives import StatevectorEstimator -estimator = StatevectorEstimator() -``` - - - - Instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). - -```python -from qiskit.primitives import Estimator -estimator = Estimator() -``` - - - - -### Run and get results - -This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one -observable. - - - - - Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) - method, which returns an instance of ... You can get the results from the - job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) - with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method. - -```python -job = estimator.run([(qc, observable, parameter_values)]) -result = job.result() -print(f" > Result class: {type(result)}") -``` -```text -... (TODO:add output) -EstimatorResult(values=array([4.]), metadata=[{}]) -``` - - - Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, - which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the - job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) - with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - -```python -job = estimator.run(qc, observable, parameter_values) -result = job.result() -print(f" > Result class: {type(result)}") -``` -```text -... (TODO:add output) -EstimatorResult(values=array([4.]), metadata=[{}]) -``` - - - -#### Get the expected value from the result - - - - - The primitives V2 result outputs an array of `PubResult`s, where each item of the array is a `PubResult` object - that contains in its data the array of evaluations corresponding to every circuit-observable combination in the Pub. - To retrieve the expectation values and metadata for the first - (and in this case, only) circuit evaluation, we must access the evaluation `data` for PUB 0: - -```python -print(f" > Expectation value: {result[0].data.evs}") -print(f" > Metadata: {result[0].metadata}") -``` -```text -... (TODO:add output) -... -``` - - - - The primitives V1 result stores an array of values that can be accessed through the attribute - [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th - element is the expectation value corresponding to the `i`th circuit and `i`th observable. - To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array. - -```python -print(f" > Expectation value: {result.values[0]}") -print(f" > Metadata: {result.metadata}") -``` - -```text -... (TODO:add output) -... -``` - - - - -### Set Estimator run options - -By default, the reference Estimator performs an exact statevector calculation based on the -[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. -However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). - -With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined. -The new interface accepts a `precision` argument that expresses the error bars that the -primitive implementation should target for expectation values estimates, -instead of the number of `shots` used in the V1 interface. - - - - - The sampling overhead is now called `precision`, and is defined exclusively at the `.run()` - method level. This allows for a more finely-grained tuning of the option all the way to the PUB level. - - ```python - # Estimate expectation values for two PUBs, both with 0.05 precision. - estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) - ``` - - - - - - The V1 interface specifies shots in the following ways: - - - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. - - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. - - ```python - job = estimator.run(qc, observable, shots=2048, seed=123) - result = job.result() - print(result) - ``` - - - - -## Use the reference `Sampler` - -Similarly to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`: -the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the -[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) -implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization -features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the -legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from -the output probability distributions, but they are expressed in different terms: - -- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or "counts" - for each bitstring present in the output distribution. -- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states. - -The following code prepares the inputs used in the examples that follow. Note that -these examples run a single parametrized circuit, but you can also run the Sampler -on non-parametrized circuits. - -```python -from qiskit import QuantumCircuit - -qc = QuantumCircuit(2) -qc.h(0) -qc.cx(0,1) -qc.measure_all() -qc.draw("mpl", style="iqp") -``` - -![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png "Initial QuantumCircuit") - - -Any quantum circuit passed to a Sampler **must** include measurements. - - -### Initialize `Sampler` - -To use the Sampler V2 implementation, follow the instructions to instantiate a -[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain -your pre-existing workflow using a Sampler V1 implementation, you can also use the -[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. - - - - ```python -from qiskit.primitives import StatevectorSampler - -sampler = StatevectorSampler() -``` - - - - ```python -from qiskit.primitives import Sampler - -sampler = Sampler() -``` - - - -### Run and get results - - - - ```python - # execute 1 circuit with 3 parameter sets using Sampler V2 - job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) - counts = job.result()[0].data.meas.get_counts() - ``` - V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result. - Therefore, you can run different circuits with various parameter/observable combinations, - which was not always possible in the V1 interface: - - ```python - # execute 2 circuits with 1 parameter set using Sampler V2 - job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)]) - counts1 = job.result() - counts2 = job.result() - ``` - - - - Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) - method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). - You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) - with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - - ```python - job = sampler.run(qc) - result = job.result() - print(result) - ``` - - ```python - SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) - ``` - - - -### Get the probability distribution or measurement outcome - -As mentioned above, the result retrieval step is different between V1 and V2 interfaces. - -The V1 sampler gives access to quasi-probability distributions. - -The V2 sampler returns measurement outcome samples in the form of **bitstrings** or -**counts**. The bitstrings show the measurement outcomes, preserving the shot -order in which they were measured. The V2 sampler result objects organize -data in terms of their input circuits' classical register names, for -compatibility with dynamic circuits. - - - - - The name of the classical register defaults to `"meas"`. - This name will be used later to access the measurement bitstrings. - - ```python - # Define quantum circuit with 2 qubits - circuit = QuantumCircuit(2) - circuit.h(0) - circuit.cx(0, 1) - circuit.measure_all() - circuit.draw() - ``` - ```python - # Run using V2 sampler - result = sampler_v2.run([circuit]).result() - # Access result data for PUB 0 - data_pub = result[0].data - # Access bitstring for the classical register "meas" - bitstring = data_pub.meas.get_bitstring() - print(f"The bitstring shape is: {bitstring.shape}") - # Get counts for the classical register "meas" - counts = data_pub.meas.get_counts() - print(f"The counts are: {counts}") - ``` - ```text - The bitstring shape is: (1024, 1) - The counts are: {'00': 523, '11': 501} - ``` - - - - - -A quasi-probability distribution differs from a probability distribution in that negative values are also allowed. -However, the quasi-probabilities must sum up to 1 like probabilities. -Negative quasi-probabilities may appear when using error mitigation techniques. - - ```python - # Define quantum circuit with 2 qubits - circuit = QuantumCircuit(2) - circuit.h(0) - circuit.cx(0, 1) - circuit.measure_all() - circuit.draw() - ``` - - ```python - # Run using V1 sampler - result = sampler_v1.run(circuit).result() - quasi_dist = result.quasi_dists[0] - print(f"The quasi-probability distribution is: {quasi_dist}") - ``` - ```text - The quasi-probability distribution is: {0: 0.5, 3: 0.5} - ``` - - If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. - - ```python - print(quasi_dist.binary_probabilities()) - ``` - - ```python - {'00': 0.4999999999999999, '11': 0.4999999999999999} - ``` - - - - -### Change run options - -By default, the reference Sampler performs an exact statevector calculation based on the -[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. -However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). - -With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined. -The new interface accepts a `shots` argument that can be defined at the "PUB level". - - - - - ```python - # Sample two circuits at 128 shots each. - sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) - ``` - - - - - - The V1 interface specifies shots in the following ways: - - - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. - - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. - - ```python - job = estimator.run(qc, observable, shots=2048, seed=123) - result = job.result() - print(result) - ``` - - - - -## Next steps - - - - For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer). - - To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial. - - Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference. - - Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference. - - Learn how to run on a physical system in the [Run](../run) section. - \ No newline at end of file From 46144a6646879ed081d57e942d2e930ac31d7015 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:32:53 -0400 Subject: [PATCH 30/60] add in one more output --- .../simulate-with-qiskit-primitives.ipynb | 79 ++++++++++++++----- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb index bfec642ce45..05cb8fadc1b 100644 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -2,7 +2,6 @@ "cells": [ { "cell_type": "markdown", - "id": "d2df2a32-dca3-4da8-9786-488203bd063b", "metadata": {}, "source": [ "# Exact simulation with Qiskit primitives" @@ -10,7 +9,6 @@ }, { "cell_type": "markdown", - "id": "c623b6f4-cbb8-4ec2-9db2-8f867a117740", "metadata": {}, "source": [ "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", @@ -25,7 +23,6 @@ }, { "cell_type": "markdown", - "id": "8366190d-e993-4b26-9d68-a6c1157be489", "metadata": {}, "source": [ "## Use the reference `Estimator`\n", @@ -50,7 +47,6 @@ { "cell_type": "code", "execution_count": 1, - "id": "f129715c-80d1-4ecb-acb2-ef6f1fd14fa6", "metadata": {}, "outputs": [ { @@ -81,7 +77,6 @@ { "cell_type": "code", "execution_count": 2, - "id": "ed97b688-03b2-4b40-be95-dbd386e440b0", "metadata": {}, "outputs": [], "source": [ @@ -95,7 +90,6 @@ }, { "cell_type": "markdown", - "id": "23f43e76-7af2-430b-afa3-3fe8ba982aab", "metadata": {}, "source": [ "### Initialize an Estimator\n", @@ -128,7 +122,6 @@ }, { "cell_type": "markdown", - "id": "0afa247f-7b6d-4c4a-b543-934747eb0016", "metadata": {}, "source": [ "### Run and get results\n", @@ -173,7 +166,6 @@ }, { "cell_type": "markdown", - "id": "06beb167-00d9-43e0-837e-09660471a9f3", "metadata": {}, "source": [ "#### Get the expected value from the result\n", @@ -217,7 +209,6 @@ }, { "cell_type": "markdown", - "id": "e327b0ab-2bf5-40c1-ae86-70b1a3f7f2ea", "metadata": {}, "source": [ "### Set Estimator run options\n", @@ -262,7 +253,6 @@ }, { "cell_type": "markdown", - "id": "9ae0d76a-0e99-413f-b370-b09cf2eec844", "metadata": {}, "source": [ "## Use the reference `Sampler`\n", @@ -286,8 +276,7 @@ }, { "cell_type": "code", - "execution_count": 5, - "id": "711c6bff-3d48-4035-8b67-f789834dbbda", + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -297,7 +286,7 @@ "
" ] }, - "execution_count": 5, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -314,7 +303,6 @@ }, { "cell_type": "markdown", - "id": "470ed0fb-3481-4203-91c6-0a192270e0e0", "metadata": {}, "source": [ "\n", @@ -322,9 +310,51 @@ "" ] }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
        ┌───┐      ░ ┌─┐   \n",
+       "   q_0: ┤ H ├──■───░─┤M├───\n",
+       "        └───┘┌─┴─┐ ░ └╥┘┌─┐\n",
+       "   q_1: ─────┤ X ├─░──╫─┤M├\n",
+       "             └───┘ ░  ║ └╥┘\n",
+       "meas: 2/══════════════╩══╩═\n",
+       "                      0  1 
" + ], + "text/plain": [ + " ┌───┐ ░ ┌─┐ \n", + " q_0: ┤ H ├──■───░─┤M├───\n", + " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", + " q_1: ─────┤ X ├─░──╫─┤M├\n", + " └───┘ ░ ║ └╥┘\n", + "meas: 2/══════════════╩══╩═\n", + " 0 1 " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# DELETE THIS CELL \n", + "from qiskit.primitives import StatevectorSampler\n", + "\n", + "sampler = StatevectorSampler()\n", + "circuit = QuantumCircuit(2)\n", + "circuit.h(0)\n", + "circuit.cx(0, 1)\n", + "circuit.measure_all()\n", + "circuit.draw()\n" + ] + }, { "cell_type": "markdown", - "id": "f8a14653-f2ca-4943-83a6-4a9621015d31", "metadata": {}, "source": [ "### Initialize `Sampler`\n", @@ -355,7 +385,6 @@ }, { "cell_type": "markdown", - "id": "2dd4fd9e-8e6a-4371-a135-bd4ff9a341b2", "metadata": {}, "source": [ "### Run and get results\n", @@ -400,7 +429,6 @@ }, { "cell_type": "markdown", - "id": "fc701e56-2bc9-49aa-ada6-103a23ef0fbe", "metadata": {}, "source": [ "### Get the probability distribution or measurement outcome\n", @@ -429,6 +457,17 @@ " circuit.measure_all()\n", " circuit.draw()\n", " ```\n", + " \n", + " ```text\n", + " ┌───┐ ░ ┌─┐ \n", + " q_0: ┤ H ├──■───░─┤M├───\n", + " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", + " q_1: ─────┤ X ├─░──╫─┤M├\n", + " └───┘ ░ ║ └╥┘\n", + "meas: 2/══════════════╩══╩═\n", + " 0 1 \n", + " ```\n", + " \n", " ```python\n", " # Run using V2 sampler\n", " result = sampler_v2.run([circuit]).result()\n", @@ -489,7 +528,6 @@ }, { "cell_type": "markdown", - "id": "164ebfeb-9f7e-4cff-96e6-02b7e1eb7dbd", "metadata": {}, "source": [ "### Change run options\n", @@ -533,7 +571,6 @@ }, { "cell_type": "markdown", - "id": "1c1e8c2d-90df-4d24-bce7-491ad18b75b8", "metadata": {}, "source": [ "## Next steps\n", @@ -551,7 +588,7 @@ "metadata": { "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -565,7 +602,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3" + "version": "3.12.0" }, "title": "Exact simulation with Qiskit primitives" }, From 6284bef14588579c993bbcedb13096b4a099833e Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:36:56 -0400 Subject: [PATCH 31/60] Update simulate-with-qiskit-primitives.ipynb --- .../simulate-with-qiskit-primitives.ipynb | 58 +++---------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb index 05cb8fadc1b..fb3301e1d5e 100644 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -310,49 +310,6 @@ "" ] }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
        ┌───┐      ░ ┌─┐   \n",
-       "   q_0: ┤ H ├──■───░─┤M├───\n",
-       "        └───┘┌─┴─┐ ░ └╥┘┌─┐\n",
-       "   q_1: ─────┤ X ├─░──╫─┤M├\n",
-       "             └───┘ ░  ║ └╥┘\n",
-       "meas: 2/══════════════╩══╩═\n",
-       "                      0  1 
" - ], - "text/plain": [ - " ┌───┐ ░ ┌─┐ \n", - " q_0: ┤ H ├──■───░─┤M├───\n", - " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", - " q_1: ─────┤ X ├─░──╫─┤M├\n", - " └───┘ ░ ║ └╥┘\n", - "meas: 2/══════════════╩══╩═\n", - " 0 1 " - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# DELETE THIS CELL \n", - "from qiskit.primitives import StatevectorSampler\n", - "\n", - "sampler = StatevectorSampler()\n", - "circuit = QuantumCircuit(2)\n", - "circuit.h(0)\n", - "circuit.cx(0, 1)\n", - "circuit.measure_all()\n", - "circuit.draw()\n" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -457,15 +414,14 @@ " circuit.measure_all()\n", " circuit.draw()\n", " ```\n", - " \n", " ```text\n", - " ┌───┐ ░ ┌─┐ \n", - " q_0: ┤ H ├──■───░─┤M├───\n", - " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", - " q_1: ─────┤ X ├─░──╫─┤M├\n", - " └───┘ ░ ║ └╥┘\n", - "meas: 2/══════════════╩══╩═\n", - " 0 1 \n", + " ┌───┐ ░ ┌─┐ \n", + " q_0: ┤ H ├──■───░─┤M├───\n", + " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", + " q_1: ─────┤ X ├─░──╫─┤M├\n", + " └───┘ ░ ║ └╥┘\n", + " meas: 2/══════════════╩══╩═\n", + " 0 1 \n", " ```\n", " \n", " ```python\n", From f7e836f0656b672da433b9334497c66e49b98041 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Fri, 5 Apr 2024 13:40:05 -0400 Subject: [PATCH 32/60] tox --- .../simulate-with-qiskit-primitives.ipynb | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb index fb3301e1d5e..c8e0107b3c8 100644 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "235b9def-4c99-4511-87dc-fe972acd1249", "metadata": {}, "source": [ "# Exact simulation with Qiskit primitives" @@ -9,6 +10,7 @@ }, { "cell_type": "markdown", + "id": "eda9656b-3403-40e3-a466-6007466adb93", "metadata": {}, "source": [ "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", @@ -23,6 +25,7 @@ }, { "cell_type": "markdown", + "id": "343d1fc6-f999-469c-9708-7536c3238b08", "metadata": {}, "source": [ "## Use the reference `Estimator`\n", @@ -47,6 +50,7 @@ { "cell_type": "code", "execution_count": 1, + "id": "c8b516bd-1a8a-4549-9264-e92d7ab29aa4", "metadata": {}, "outputs": [ { @@ -77,6 +81,7 @@ { "cell_type": "code", "execution_count": 2, + "id": "e5beee91-315e-4f0e-b9dd-7a8faeb007a5", "metadata": {}, "outputs": [], "source": [ @@ -90,6 +95,7 @@ }, { "cell_type": "markdown", + "id": "97bf4aa1-189b-42e9-b77d-6d58f46386a5", "metadata": {}, "source": [ "### Initialize an Estimator\n", @@ -122,6 +128,7 @@ }, { "cell_type": "markdown", + "id": "6173f09d-bd0e-4b4d-882e-705a27b298ee", "metadata": {}, "source": [ "### Run and get results\n", @@ -166,6 +173,7 @@ }, { "cell_type": "markdown", + "id": "60922742-7149-4b92-add2-0e8e258b4486", "metadata": {}, "source": [ "#### Get the expected value from the result\n", @@ -209,6 +217,7 @@ }, { "cell_type": "markdown", + "id": "e9d18e6d-e804-426b-a202-dfe065f7649d", "metadata": {}, "source": [ "### Set Estimator run options\n", @@ -253,6 +262,7 @@ }, { "cell_type": "markdown", + "id": "fa409517-8a93-43fe-94a7-4dd33e992331", "metadata": {}, "source": [ "## Use the reference `Sampler`\n", @@ -277,6 +287,7 @@ { "cell_type": "code", "execution_count": 3, + "id": "1699fb2f-19a7-4d48-b96a-d5ca1e302825", "metadata": {}, "outputs": [ { @@ -303,6 +314,7 @@ }, { "cell_type": "markdown", + "id": "d84e2e65-8417-49df-8d7e-ffe5f65c0da7", "metadata": {}, "source": [ "\n", @@ -312,6 +324,7 @@ }, { "cell_type": "markdown", + "id": "e89bf86e-a91b-47ca-9660-b515737c7124", "metadata": {}, "source": [ "### Initialize `Sampler`\n", @@ -342,6 +355,7 @@ }, { "cell_type": "markdown", + "id": "fc686469-b3e0-4dd5-bce5-d41934af6f37", "metadata": {}, "source": [ "### Run and get results\n", @@ -386,6 +400,7 @@ }, { "cell_type": "markdown", + "id": "0a2392f3-d923-45a3-a8e6-cc2fa0a9af10", "metadata": {}, "source": [ "### Get the probability distribution or measurement outcome\n", @@ -415,15 +430,15 @@ " circuit.draw()\n", " ```\n", " ```text\n", - " ┌───┐ ░ ┌─┐ \n", + " ┌───┐ ░ ┌─┐\n", " q_0: ┤ H ├──■───░─┤M├───\n", " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", " q_1: ─────┤ X ├─░──╫─┤M├\n", " └───┘ ░ ║ └╥┘\n", " meas: 2/══════════════╩══╩═\n", - " 0 1 \n", + " 0 1\n", " ```\n", - " \n", + "\n", " ```python\n", " # Run using V2 sampler\n", " result = sampler_v2.run([circuit]).result()\n", @@ -484,6 +499,7 @@ }, { "cell_type": "markdown", + "id": "e14406a4-1265-4e68-9248-391d43799f61", "metadata": {}, "source": [ "### Change run options\n", @@ -527,6 +543,7 @@ }, { "cell_type": "markdown", + "id": "abc1c15b-0d07-4e7b-9396-6825e2289c3e", "metadata": {}, "source": [ "## Next steps\n", @@ -544,7 +561,7 @@ "metadata": { "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -558,7 +575,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3" }, "title": "Exact simulation with Qiskit primitives" }, From cf6122f125b5903e2b7f8828b788fb51e889f54c Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 9 Apr 2024 19:41:56 -0400 Subject: [PATCH 33/60] convert to mdx --- .../simulate-with-qiskit-primitives.ipynb | 584 ------------------ .../simulate-with-qiskit-primitives.mdx | 432 +++++++++++++ .../estimator-initialize.png | Bin 3045 -> 5067 bytes .../sampler-initialize.png | Bin 8687 -> 10323 bytes 4 files changed, 432 insertions(+), 584 deletions(-) delete mode 100644 docs/verify/simulate-with-qiskit-primitives.ipynb create mode 100644 docs/verify/simulate-with-qiskit-primitives.mdx diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb deleted file mode 100644 index c8e0107b3c8..00000000000 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ /dev/null @@ -1,584 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "235b9def-4c99-4511-87dc-fe972acd1249", - "metadata": {}, - "source": [ - "# Exact simulation with Qiskit primitives" - ] - }, - { - "cell_type": "markdown", - "id": "eda9656b-3403-40e3-a466-6007466adb93", - "metadata": {}, - "source": [ - "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", - "modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation\n", - "techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives).\n", - "\n", - "The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample\n", - "from output distributions of circuits.\n", - "\n", - "The following sections show how to use the reference primitives to run your workflow locally." - ] - }, - { - "cell_type": "markdown", - "id": "343d1fc6-f999-469c-9708-7536c3238b08", - "metadata": {}, - "source": [ - "## Use the reference `Estimator`\n", - "\n", - "There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector\n", - "simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the\n", - "[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator)\n", - "implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization\n", - "features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the\n", - "legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally\n", - "computed expectation values.\n", - "\n", - "The following code prepares the inputs that will be used in the examples that follow. The expected input type for the\n", - "observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that\n", - "the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits.\n", - "\n", - "\n", - " Any circuit passed to an Estimator must **not** include any **measurements**.\n", - "" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "c8b516bd-1a8a-4549-9264-e92d7ab29aa4", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from qiskit import QuantumCircuit\n", - "from qiskit.circuit import Parameter\n", - "from qiskit.quantum_info import SparsePauliOp\n", - "\n", - "# circuit for which you want to obtain the expected value\n", - "qc = QuantumCircuit(2)\n", - "qc.ry(Parameter('theta'), 0)\n", - "qc.h(0)\n", - "qc.cx(0,1)\n", - "qc.draw(\"mpl\", style=\"iqp\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "e5beee91-315e-4f0e-b9dd-7a8faeb007a5", - "metadata": {}, - "outputs": [], - "source": [ - "# observable(s) whose expected values you want to compute\n", - "observable = SparsePauliOp([\"II\", \"XX\", \"YY\", \"ZZ\"], coeffs=[1, 1, -1, 1])\n", - "\n", - "# value(s) for the circuit parameter(s)\n", - "import numpy as np\n", - "parameter_values = [[0], [np.pi/6], [np.pi/2]]" - ] - }, - { - "cell_type": "markdown", - "id": "97bf4aa1-189b-42e9-b77d-6d58f46386a5", - "metadata": {}, - "source": [ - "### Initialize an Estimator\n", - "\n", - "To use the Estimator V2 implementation, follow the instructions to instantiate a\n", - "[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain\n", - "your pre-existing workflow using an Estimator V1 implementation, you can also use the\n", - "[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class.\n", - "\n", - "\n", - " \n", - " Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator).\n", - "\n", - "```python\n", - "from qiskit.primitives import StatevectorEstimator\n", - "estimator = StatevectorEstimator()\n", - "```\n", - " \n", - "\n", - " \n", - " Instantiate a [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator).\n", - "\n", - "```python\n", - "from qiskit.primitives import Estimator\n", - "estimator = Estimator()\n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "6173f09d-bd0e-4b4d-882e-705a27b298ee", - "metadata": {}, - "source": [ - "### Run and get results\n", - "\n", - "This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one\n", - "observable.\n", - "\n", - "\n", - "\n", - " \n", - " Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run)\n", - " method, which returns an instance of a [PrimitiveJob](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the\n", - " job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object)\n", - " with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method.\n", - "\n", - "```python\n", - "job = estimator.run([(qc, observable, parameter_values)])\n", - "result = job.result()\n", - "print(f\" > Result class: {type(result)}\")\n", - "```\n", - "```text\n", - " > Result class: \n", - "```\n", - " \n", - " \n", - " Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method,\n", - " which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the\n", - " job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object)\n", - " with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", - "\n", - "```python\n", - "job = estimator.run([qc]*3, [observable]*3, parameter_values)\n", - "result = job.result()\n", - "print(f\" > Result class: {type(result)}\")\n", - "```\n", - "```text\n", - " > Result class: \n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "60922742-7149-4b92-add2-0e8e258b4486", - "metadata": {}, - "source": [ - "#### Get the expected value from the result\n", - "\n", - "\n", - " \n", - "\n", - " The primitives V2 result outputs an array of [`PubResult`s](/api/qiskit/qiskit.primitives.PubResult#pubresult), where each item of the array is a `PubResult` object\n", - " that contains in its data the array of evaluations corresponding to every circuit-observable combination in the PUB.\n", - " To retrieve the expectation values and metadata for the first\n", - " (and in this case, only) circuit evaluation, we must access the evaluation [`data`](/api/qiskit/qiskit.primitives.PubResult#data) for PUB 0:\n", - "\n", - "```python\n", - "print(f\" > Expectation value: {result[0].data.evs}\")\n", - "print(f\" > Metadata: {result[0].metadata}\")\n", - "```\n", - "```text\n", - " > Expectation value: [4. 3.73205081 2. ]\n", - " > Metadata: {'precision': 0.0}\n", - "```\n", - " \n", - " \n", - "\n", - " The primitives V1 result stores an array of values that can be accessed through the attribute\n", - " [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th\n", - " element is the expectation value corresponding to the `i`th circuit and `i`th observable.\n", - " To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array.\n", - "\n", - "```python\n", - "print(f\" > Expectation value: {result.values[0]}\")\n", - "print(f\" > Metadata: {result.metadata}\")\n", - "```\n", - "\n", - "```text\n", - " > Expectation value: 3.999999999999999\n", - " > Metadata: [{}, {}, {}]\n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "e9d18e6d-e804-426b-a202-dfe065f7649d", - "metadata": {}, - "source": [ - "### Set Estimator run options\n", - "\n", - "By default, the reference Estimator performs an exact statevector calculation based on the\n", - "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", - "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", - "\n", - "With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined.\n", - "The new interface accepts a `precision` argument that expresses the error bars that the\n", - "primitive implementation should target for expectation values estimates,\n", - "instead of the number of `shots` used in the V1 interface.\n", - "\n", - "\n", - " \n", - "\n", - " The sampling overhead is now called `precision`, and is defined exclusively at the `.run()`\n", - " method level. This allows for a more finely-grained tuning of the option all the way to the PUB level.\n", - "\n", - " ```python\n", - " # Estimate expectation values for two PUBs, both with 0.05 precision.\n", - " estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)\n", - " ```\n", - "\n", - " \n", - "\n", - " \n", - "\n", - " The V1 interface specifies shots in the following ways:\n", - "\n", - " - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.\n", - " - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.\n", - "\n", - " ```python\n", - " job = estimator.run(qc, observable, shots=2048, seed=123)\n", - " result = job.result()\n", - " print(result)\n", - " ```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "fa409517-8a93-43fe-94a7-4dd33e992331", - "metadata": {}, - "source": [ - "## Use the reference `Sampler`\n", - "\n", - "Similar to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`:\n", - "the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the\n", - "[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler)\n", - "implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization\n", - "features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the\n", - "legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from\n", - "the output probability distributions, but they are expressed in different terms:\n", - "\n", - "- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or \"counts\"\n", - " for each bitstring present in the output distribution.\n", - "- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states.\n", - "\n", - "The following code prepares the inputs used in the examples that follow. Note that\n", - "these examples run a single parametrized circuit, but you can also run the Sampler\n", - "on non-parametrized circuits." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "1699fb2f-19a7-4d48-b96a-d5ca1e302825", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from qiskit import QuantumCircuit\n", - "\n", - "qc = QuantumCircuit(2)\n", - "qc.h(0)\n", - "qc.cx(0,1)\n", - "qc.measure_all()\n", - "qc.draw(\"mpl\", style=\"iqp\")" - ] - }, - { - "cell_type": "markdown", - "id": "d84e2e65-8417-49df-8d7e-ffe5f65c0da7", - "metadata": {}, - "source": [ - "\n", - "Any quantum circuit passed to a Sampler **must** include measurements.\n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "e89bf86e-a91b-47ca-9660-b515737c7124", - "metadata": {}, - "source": [ - "### Initialize `Sampler`\n", - "\n", - "To use the Sampler V2 implementation, follow the instructions to instantiate a\n", - "[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain\n", - "your pre-existing workflow using a Sampler V1 implementation, you can also use the\n", - "[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class.\n", - "\n", - "\n", - " \n", - " ```python\n", - "from qiskit.primitives import StatevectorSampler\n", - "\n", - "sampler = StatevectorSampler()\n", - "```\n", - " \n", - "\n", - " \n", - " ```python\n", - "from qiskit.primitives import Sampler\n", - "\n", - "sampler = Sampler()\n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "fc686469-b3e0-4dd5-bce5-d41934af6f37", - "metadata": {}, - "source": [ - "### Run and get results\n", - "\n", - "\n", - " \n", - " ```python\n", - " # execute 1 circuit with 3 parameter sets using Sampler V2\n", - " job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])\n", - " counts = job.result()[0].data.meas.get_counts()\n", - " ```\n", - " V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result.\n", - " Therefore, you can run different circuits with various parameter/observable combinations,\n", - " which was not always possible in the V1 interface:\n", - "\n", - " ```python\n", - " # execute 2 circuits with 1 parameter set using Sampler V2\n", - " job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])\n", - " counts1 = job.result()\n", - " counts2 = job.result()\n", - " ```\n", - " \n", - "\n", - " \n", - " Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)\n", - " method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1).\n", - " You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object)\n", - " with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", - "\n", - " ```python\n", - " job = sampler.run(qc)\n", - " result = job.result()\n", - " print(result)\n", - " ```\n", - "\n", - " ```python\n", - " SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}])\n", - " ```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "0a2392f3-d923-45a3-a8e6-cc2fa0a9af10", - "metadata": {}, - "source": [ - "### Get the probability distribution or measurement outcome\n", - "\n", - "As mentioned above, the result retrieval step is different between V1 and V2 interfaces.\n", - "\n", - "The V1 sampler gives access to quasi-probability distributions.\n", - "\n", - "The V2 sampler returns measurement outcome samples in the form of **bitstrings** or\n", - "**counts**. The bitstrings show the measurement outcomes, preserving the shot\n", - "order in which they were measured. The V2 sampler result objects organize\n", - "data in terms of their input circuits' classical register names, for\n", - "compatibility with dynamic circuits.\n", - "\n", - "\n", - "\n", - " \n", - " The name of the classical register defaults to `\"meas\"`.\n", - " This name will be used later to access the measurement bitstrings.\n", - "\n", - " ```python\n", - " # Define quantum circuit with 2 qubits\n", - " circuit = QuantumCircuit(2)\n", - " circuit.h(0)\n", - " circuit.cx(0, 1)\n", - " circuit.measure_all()\n", - " circuit.draw()\n", - " ```\n", - " ```text\n", - " ┌───┐ ░ ┌─┐\n", - " q_0: ┤ H ├──■───░─┤M├───\n", - " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", - " q_1: ─────┤ X ├─░──╫─┤M├\n", - " └───┘ ░ ║ └╥┘\n", - " meas: 2/══════════════╩══╩═\n", - " 0 1\n", - " ```\n", - "\n", - " ```python\n", - " # Run using V2 sampler\n", - " result = sampler_v2.run([circuit]).result()\n", - " # Access result data for PUB 0\n", - " data_pub = result[0].data\n", - " # Access bitstring for the classical register \"meas\"\n", - " bitstring = data_pub.meas.get_bitstring()\n", - " print(f\"The bitstring shape is: {bitstring.shape}\")\n", - " # Get counts for the classical register \"meas\"\n", - " counts = data_pub.meas.get_counts()\n", - " print(f\"The counts are: {counts}\")\n", - " ```\n", - " ```text\n", - " The bitstring shape is: (1024, 1)\n", - " The counts are: {'00': 523, '11': 501}\n", - " ```\n", - " \n", - "\n", - " \n", - "\n", - "\n", - "A quasi-probability distribution differs from a probability distribution in that negative values are also allowed.\n", - "However, the quasi-probabilities must sum up to 1 like probabilities.\n", - "Negative quasi-probabilities may appear when using error mitigation techniques.\n", - "\n", - " ```python\n", - " # Define quantum circuit with 2 qubits\n", - " circuit = QuantumCircuit(2)\n", - " circuit.h(0)\n", - " circuit.cx(0, 1)\n", - " circuit.measure_all()\n", - " circuit.draw()\n", - " ```\n", - "\n", - " ```python\n", - " # Run using V1 sampler\n", - " result = sampler_v1.run(circuit).result()\n", - " quasi_dist = result.quasi_dists[0]\n", - " print(f\"The quasi-probability distribution is: {quasi_dist}\")\n", - " ```\n", - " ```text\n", - " The quasi-probability distribution is: {0: 0.5, 3: 0.5}\n", - " ```\n", - "\n", - " If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method.\n", - "\n", - " ```python\n", - " print(quasi_dist.binary_probabilities())\n", - " ```\n", - "\n", - " ```python\n", - " {'00': 0.4999999999999999, '11': 0.4999999999999999}\n", - " ```\n", - "\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "e14406a4-1265-4e68-9248-391d43799f61", - "metadata": {}, - "source": [ - "### Change run options\n", - "\n", - "By default, the reference Sampler performs an exact statevector calculation based on the\n", - "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", - "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", - "\n", - "With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined.\n", - "The new interface accepts a `shots` argument that can be defined at the \"PUB level\".\n", - "\n", - "\n", - " \n", - "\n", - " ```python\n", - " # Sample two circuits at 128 shots each.\n", - " sampler_v2.run([circuit1, circuit2], shots=128)\n", - " # Sample two circuits at different amounts of shots. The \"None\"s are necessary\n", - " # as placeholders\n", - " # for the lack of parameter values in this example.\n", - " sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])\n", - " ```\n", - "\n", - " \n", - "\n", - " \n", - "\n", - " The V1 interface specifies shots in the following ways:\n", - "\n", - " - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.\n", - " - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.\n", - "\n", - " ```python\n", - " job = estimator.run(qc, observable, shots=2048, seed=123)\n", - " result = job.result()\n", - " print(result)\n", - " ```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "id": "abc1c15b-0d07-4e7b-9396-6825e2289c3e", - "metadata": {}, - "source": [ - "## Next steps\n", - "\n", - "\n", - " - For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer).\n", - " - To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial.\n", - " - Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference.\n", - " - Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference.\n", - " - Learn how to run on a physical system in the [Run](../run) section.\n", - "" - ] - } - ], - "metadata": { - "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3" - }, - "title": "Exact simulation with Qiskit primitives" - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx new file mode 100644 index 00000000000..16e412a8d90 --- /dev/null +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -0,0 +1,432 @@ +--- +title: Exact simulation with Qiskit primitives +description: How to perform exact simulation of quantum circuits using primitives in Qiskit. +--- +# Exact simulation with Qiskit primitives + +The reference primitives in Qiskit perform local statevector simulations. These simulations do not support +modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation +techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives). + +The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample +from output distributions of circuits. + +The following sections show how to use the reference primitives to run your workflow locally. + +## Use the reference `Estimator` + +There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector +simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the +[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) +implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization +features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the +legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally +computed expectation values. + +The following code prepares the inputs that will be used in the examples that follow. The expected input type for the +observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that +the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits. + + + Any circuit passed to an Estimator must **not** include any **measurements**. + +```python +from qiskit import QuantumCircuit +from qiskit.circuit import Parameter +from qiskit.quantum_info import SparsePauliOp + +# circuit for which you want to obtain the expected value +qc = QuantumCircuit(2) +qc.ry(Parameter('theta'), 0) +qc.h(0) +qc.cx(0,1) +qc.draw("mpl", style="iqp") +``` +![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png "Initial QuantumCircuit") + +```python +# observable(s) whose expected values you want to compute +observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) + +# value(s) for the circuit parameter(s) +import numpy as np +parameter_values = [[0], [np.pi/6], [np.pi/2]] +``` +### Initialize Estimator + +To use the Estimator V2 implementation, follow the instructions to instantiate a +[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain +your pre-existing workflow using an Estimator V1 implementation, you can also use the +[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. + + + + Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). + +```python +from qiskit.primitives import StatevectorEstimator +estimator = StatevectorEstimator() +``` + + + + Instantiate a [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). + +```python +from qiskit.primitives import Estimator +estimator = Estimator() +``` + + + +### Run and get results + +This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one +observable. + + + + + Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) + method, which returns an instance of a [PrimitiveJob](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the + job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) + with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method. + +```python +job = estimator.run([(qc, observable, parameter_values)]) +result = job.result() +print(f" > Result class: {type(result)}") +``` +```text + > Result class: +``` + + + Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, + which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the + job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) + with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. + +```python +job = estimator.run([qc]*3, [observable]*3, parameter_values) +result = job.result() +print(f" > Result class: {type(result)}") +``` +```text + > Result class: +``` + + + +#### Get the expected value from the result + + + + + The primitives V2 result outputs an array of [`PubResult`s](/api/qiskit/qiskit.primitives.PubResult#pubresult), where each item of the array is a `PubResult` object + that contains in its data the array of evaluations corresponding to every circuit-observable combination in the PUB. + To retrieve the expectation values and metadata for the first + (and in this case, only) circuit evaluation, we must access the evaluation [`data`](/api/qiskit/qiskit.primitives.PubResult#data) for PUB 0: + +```python +print(f" > Expectation value: {result[0].data.evs}") +print(f" > Metadata: {result[0].metadata}") +``` +```text + > Expectation value: [4. 3.73205081 2. ] + > Metadata: {'precision': 0.0} +``` + + + + The primitives V1 result stores an array of values that can be accessed through the attribute + [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th + element is the expectation value corresponding to the `i`th circuit and `i`th observable. + To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array. + +```python +print(f" > Expectation value: {result.values[0]}") +print(f" > Metadata: {result.metadata}") +``` + +```text + > Expectation value: 3.999999999999999 + > Metadata: [{}, {}, {}] +``` + + + +### Set Estimator run options + +By default, the reference Estimator performs an exact statevector calculation based on the +[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. +However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). + +With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined. +The new interface accepts a `precision` argument that expresses the error bars that the +primitive implementation should target for expectation values estimates, +instead of the number of `shots` used in the V1 interface. + + + + + The sampling overhead is now called `precision`, and is defined exclusively at the `.run()` + method level. This allows for a more finely-grained tuning of the option all the way to the PUB level. + + ```python + # Estimate expectation values for two PUBs, both with 0.05 precision. + estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) + ``` + + + + + + The V1 interface specifies shots in the following ways: + + - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. + - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. + + ```python + job = estimator.run(qc, observable, shots=2048, seed=123) + result = job.result() + print(result) + ``` + + + +## Use the reference `Sampler` + +Similar to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`: +the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the +[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) +implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization +features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the +legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from +the output probability distributions, but they are expressed in different terms: + +- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or "counts" + for each bitstring present in the output distribution. +- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states. + +The following code prepares the inputs used in the examples that follow. Note that +these examples run a single parametrized circuit, but you can also run the Sampler +on non-parametrized circuits. + +```python +from qiskit import QuantumCircuit + +qc = QuantumCircuit(2) +qc.h(0) +qc.cx(0,1) +qc.measure_all() +qc.draw("mpl", style="iqp") +``` +![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png "Initial QuantumCircuit") + + +Any quantum circuit passed to a Sampler **must** include measurements. + + +### Initialize `Sampler` + +To use the Sampler V2 implementation, follow the instructions to instantiate a +[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain +your pre-existing workflow using a Sampler V1 implementation, you can also use the +[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. + + + + ```python +from qiskit.primitives import StatevectorSampler + +sampler = StatevectorSampler() +``` + + + + ```python +from qiskit.primitives import Sampler + +sampler = Sampler() +``` + + +### Run and get results + + + + ```python + # execute 1 circuit with 3 parameter sets using Sampler V2 + job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) + counts = job.result()[0].data.meas.get_counts() + ``` + V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result. + Therefore, you can run different circuits with various parameter/observable combinations, + which was not always possible in the V1 interface: + + ```python + # execute 2 circuits with 1 parameter set using Sampler V2 + job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)]) + counts1 = job.result() + counts2 = job.result() + ``` + + + + Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) + method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). + You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) + with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. + + ```python + job = sampler.run(qc) + result = job.result() + print(result) + ``` + + ```python + SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) + ``` + + +### Get the probability distribution or measurement outcome + +As mentioned above, the result retrieval step is different between V1 and V2 interfaces. + +The V1 sampler gives access to quasi-probability distributions. + +The V2 sampler returns measurement outcome samples in the form of **bitstrings** or +**counts**. The bitstrings show the measurement outcomes, preserving the shot +order in which they were measured. The V2 sampler result objects organize +data in terms of their input circuits' classical register names, for +compatibility with dynamic circuits. + + + + + The name of the classical register defaults to `"meas"`. + This name will be used later to access the measurement bitstrings. + + ```python + # Define 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 + ``` + + ```python + # Run using V2 sampler + result = sampler_v2.run([circuit]).result() + # Access result data for PUB 0 + data_pub = result[0].data + # Access bitstring for the classical register "meas" + bitstring = data_pub.meas.get_bitstring() + print(f"The bitstring shape is: {bitstring.shape}") + # Get counts for the classical register "meas" + counts = data_pub.meas.get_counts() + print(f"The counts are: {counts}") + ``` + ```text + The bitstring shape is: (1024, 1) + The counts are: {'00': 523, '11': 501} + ``` + + + + + +A quasi-probability distribution differs from a probability distribution in that negative values are also allowed. +However, the quasi-probabilities must sum up to 1 like probabilities. +Negative quasi-probabilities may appear when using error mitigation techniques. + + ```python + # Define quantum circuit with 2 qubits + circuit = QuantumCircuit(2) + circuit.h(0) + circuit.cx(0, 1) + circuit.measure_all() + circuit.draw() + ``` + + ```python + # Run using V1 sampler + result = sampler_v1.run(circuit).result() + quasi_dist = result.quasi_dists[0] + print(f"The quasi-probability distribution is: {quasi_dist}") + ``` + ```text + The quasi-probability distribution is: {0: 0.5, 3: 0.5} + ``` + + If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. + + ```python + print(quasi_dist.binary_probabilities()) + ``` + + ```python + {'00': 0.4999999999999999, '11': 0.4999999999999999} + ``` + + + + +### Change run options + +By default, the reference Sampler performs an exact statevector calculation based on the +[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. +However, this can be modified to introduce the effect of the sampling overhead (also known as "shot noise"). + +With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined. +The new interface accepts a `shots` argument that can be defined at the "PUB level". + + + + + ```python + # Sample two circuits at 128 shots each. + sampler_v2.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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) + ``` + + + + + + The V1 interface specifies shots in the following ways: + + - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. + - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. + + ```python + job = estimator.run(qc, observable, shots=2048, seed=123) + result = job.result() + print(result) + ``` + + + +## Next steps + + + - For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer). + - To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial. + - Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference. + - Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference. + - Learn how to run on a physical system in the [Run](../run) section. + \ No newline at end of file diff --git a/public/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png b/public/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png index 10f0e3ba104f4ea49baa211071550e20473fc840..07b291e6a85313f99b841104c4591a59a82335d5 100644 GIT binary patch literal 5067 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 literal 3045 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�R z#oJF;pp`XV*oHqWQQYzM=9*8JEX?KX3}aE3)R4X-jZu?K8KQ*>L_&hQC}8_IRnt$# zbxlwpK)?A|kB5ob3{*7^U6!iNZ))MspU8tq9Q^zcEyU8HZed{|uc+91G$_gK!3xg- zZRjnP80q83kI~U=WM$Dyjq1>w_rJScp6$he`7t#!(>gmlTTt5{3T1o6uDglx`Kza% z*FdTWXQOeAGo9z&g2Tj&yksR4TE?YsbWPEhIp)=*!08yZfK0rWt}YCabm)6R&P!4p zMzthBd28J&YjPZ#`woccx`BOP6u9eY@Ym%9j?Ef-2a@x3d~?E+x;+lpMgZ)d^OdE` z49LJ$%{$+=07+AHTpIiQKnHaPja4tayQ|iG`0b03(_w2G+RFf+y0a9Cz6sgr`CEQG zMaDp*Lbr8gI;?UTwumsw_bj)zvT+f7^2SfiaDLesoPsrLKdJYvi@xTRG*`=WuSeHV$j6ci%<$rHNo*49qZxy(NDtF?Ss zEBZ}Bu23TH?Md5snU$Gw;tc~ui2{&EbV>~)Qd1xPh5k?Dh>{V?Ol`p%4F^A;OKzXj zQ_(QPX_?h-p)$`pFP6RBqHf=kt;HYU28MYAJg z<0Fy^6x^%O{FDYkw9u!f@vCHSkhHNM02!8dd6Ag^B4jfk50Jbh4s+s~HwaOzDkTL0 zvgY#E7W?0}N~C6?*7|g%n`*aO3=@)+ME(H1_~T={*p!riUBt%4B?|^C5GDVza{i5N zrBMfa^kaXy4R>Z?a1h_A;e-^t;?mBJL*8cu2Z%e2^w-W#)VIX|gH1k!a#)h*|D5Fo zflvxLwu3pcyt(-Xlqda@ClBSKAI8;k(A&0wA;e=nL_0M-O-D-$NfB~-U;8Lh)MJyx z%*ApiASK6-w{#T{LY6>CRE(X#XJADw zlO};tfch(H-6yQFJo?>_G%yzY&x{~aKm^u&_Uwz}ylDOTN+gl46}g6n2I9>dR0vT1 z6?DMr^a1`22P8yTR1`@#wSCkzBJ888rw{ehN)HydlEK)J?8{G~OntaL`(!Yg-)eum za!^oD5NP@UZr%fPW&h}i_(%}eQ=by~QQs)RBCI};8RNcR?RSH`=fp2!H6tfVjUuzM z=sAq*p94x>{3fl0vr+8bTl@Yd1H;>lEF!Tc;jzsv$KBHB70$ACYd!t_4xS>F%N~x7 zr8&@#Zjv;YG3gF2M!tI{=u3ZmM*EDi6u!hHew=Rf7en3}v}?r?6Ipt@9QE#lv9I^k z+3tt!v6n4Q%G%63qz+3<5BDxk7We}^FQtx8gVce6nP&zR$LEcHB1FW*goK229wIQE zp3xHaENU8?{Q$yc>E)s|MinO~Cu@O^Ouc|fE!LkfpnsLj)wHpVKJ#&o#ZAbp|><5>U%q&A4NJfU03&1FvvwW zFD^Do8!BwBth_c+#+&r@4K<9;&t}%QuuFw1LV^GyMnk6FCvo4Qd^H+i*&$s!q-Tv$uvlQ3lt=eHxS>qd|Cln>L&|GCVxeu%vv)O6~@9UGv zjzkB|kc*SnphoCR2eFMWruzr({Ojk)i3He{q9WGkqN2=U>sXL{Ad@Mcl@23KRZ?*V z4|%@i;*MX~54hR^GUGJB(O`BJ* z@;$WpY-}3pT3C`!_@E6}P#i>bxrkirL~cEOdD0x5tX6$tTFqbcDR~|a-)#eYf#5Pl z&v|RpZ27Ztc#>xitwN9P{*B4$@=^p1vZL6xE8~SnK0ETQpxV*?AYx&dkEa2_#5-*~_>IxSS@{ewT} z^4Hb=;=zU)rpc@V;vFa zB}iusO$-Q3YexqfFE20freuq{N`W<kex?)S&lx~kub2PMdD zZGeu83lF4hIPe&@x3>Y@jLiS^604`Dr{vQXpj@DagY)y5?d|QCe*X@OjV0jF|0;jz zllLfiezwPkV91QQ#Z7_9d$~`S1+C2+=#<)$ms#s##B{RMTIPfJ}~C#y%qCM z6fYoHn5%z=FgS~Ie$4Q!LKIP~r|l6{zOmZST8n?nq@|^!U=;l*n#ri(R?JoW8L$NN zMsWmf&$U*Umi{ttut_-}5J03~{77V#S5@u&YBTD5b?&k~^(EWIKOjKjli#5Nl9jr+ zxIF*nXtc_U25kl&mGj|G1?4o+`yeV3sHmurG5osdsHhI0g!8^UwoVnFbr&sey86XU z#&3!964ZZ9acL>uqTdlNDaUh2u4Y7?*IsK+&pn8`fdMv98-V3vc6qwMKPTgiDt|@XY?xXLWm4Du})zY4n;!64^hQUHurJ6qqg=A=vNgQcd z(PE+k6~NTaj=_UfMObXwe4{m4c4u}Y80l66FWN4_1B?V9nZS#-@M$F878I}m6#|mP zZQ^Jcus%eGe4XpdGdWjRJ}oxwgll(ED%rPWuauIwmI1JMDarT?Kk)p{M6q7T`MGyr zn%DyfP#nO(#nsi-1py>G{XP5TG-Oa+Q^#?{oQTkaiAy#5`JcK!vO9ME&*Zbh z5zryj^=bQ@P-&t4xIk0>%Bmy13z3hgM~V;vYtc9n}Zl+OVj}7 zlx@kMKYyZ3*h#QJ%Q6Gz`G+Syd>{pb5eQ7+Vw+!`A2_@426)$eNn#JWh^wXaY`+8f z-35E18Nz@-91m}B?Npz7zSUaf5Kn1obc#%!yMPo5|%)36$3!;V=9 zM&)KU^mFpYcnDZ{c?p5F@^bH+)gU#b8ENGMMM}Wn)>-M;6i^$b_Z%(pj7qU-X;HvB zeklHu#Ki9a&2wia6r|w_h#-1X%t!^+uzwD)l((%I>1|O$zT$$K1i@|r(ibk)NMD~a zM9SN{S54ylpzG8M4Qc<@`yBB&Ej-~csKzlhH5K;UCIb>RAsJbL7iZAH zI6B1pY~CxSuOJZ|l2~6~Crx*beg8geEj^H0^5)z;AwWM(H5_nYe4xevE{Tcj;M1u1 zY?VV62D?~(k?lEQSEb+H-Y%e8gM?~eWFh72i4p@A?y@~0Wi>Uq#m18uC>tkdM=YJR z^U-gWsi~<9wR8zUi=}}=THnxcFuQm|3X~mNz9|+)Ml?WC(ILR{%?7PborMIDSKIAp z^8lY1zuaKVzPTmK%6zP^Z4_cn5NJ)uEryz~e-5>&T(gn-id zUh~v@JkNfQz4zz6Kfo}HHS4M~e&_$3D9uO81h}-g5CjpZswikf5bP`Xdkq^7ehc>~ z)`J%@4@G^CC(c$L-sWyEAPsX57YAn#2U`nfuNQ9aw$4t1yrR7PcbRQGJY3wx`S=|F zbpx-nn>C+sb!{nl2#$-&Gj|BWe}wvh1$oD?K@f|Ps)C#jB4c;aPecBq z_aq*Ig_u~lg?Y7nq9xsYD`7$pZ;-sUMKW{3^1XoY_HzSkSGU5VRalK=(PNe@$W+8)#B3CqCozb z4F(AbNo{1(1ST?H{2kt3RXCcM>k9{Bwe~>GyqeD)POIXX?&n`$Ct5gyV9^Cs*PJyRWPGN%b z;BOC^w5zrnrnRXx_~%0ua;LWsCZC$hRZgoL<0fz++(OttZezIAKiJ|%#?hLsP?wZ4 zS3gX@Paq~Hrkx6duyJv_a^)imctah+U}}kthA{GEHDgS%ri=`FqeeHyEr9`8HC`&1 zunu>%$4~9(kHjRkx{_!dtXfQY!(T59R)a(LcW$OEUH zz=aP-AIXx!3+-h7$EANWfILm^l$k1Xbmf)A?o}=$R?=|olAf|>9}9TpNqKpBi_6Q` z&rGrUfx&3$=;>LEWQd*q9^%W@D=p-G-wVg5Msj8$&_c0@lumvvvZM}anV7_>r}DC} zv7wigl*GpI>y_xJsH%3B8`f8ub)vm2Mz=)Pkx}uP^vu=TyRP=&P{%68(1{Sv*E=h# zs9>|Qu~j=SNtdXzV_6E(CL|?=)_HVuHX6mfeM^1UxQQGLQU;L;D^s_?lSW8zT%~(gd+qR#rrP54nttjbV`c z#)#r*mJ}>!7_*p7^$O?o1hd0sNp7yv8yQ0g8eMGmo_D8G zL8A}fUcT=*7q+@;!OqV9wu=msl#~RMCq%-yQ^sY`Z{JumW}P%2NK{>kYK|-I!Hcv@ zs_dtEi*?E`=sIF(1gnB>0vj3{mVvh+z|hrZogufn$)L}lKkpB6X6Kl;2c8~|KZbRX zXGK%-St07kz>@313CGY1&i+S}Pgiz#2_8Rwd{@5;DI!l9 zRY!Sx68~m?oeKSDd!$Jm7dbAbQXD-_c;1nh2PPc8`e#%o!icxudnq7dr8{EnVz0g4 z_o}H$90Lx2$AgEBUFDiGVNmK|2VPh>wPd>236sYnV(dX}tnZN>J0~ZblvL}O zLC?Z;UB~ovy>3v69ZvrYo}Es2kXwzCQeHtpK~8b;K-tB8X=%oE5oeSa!l3Qx%6?$& z#8gyRjYdufN4U7S%NrZko&jS_&vPx~HB0B0D%H&}vI5tmBi?Y9Z%wW`zOc6LcD9m{ z^TZaG_M$qEjjGKn#P=@EAR(rXX_})Q+pd|iuWYrd*3i%(;J$N5V=;d?Dmwb3uC1Qm z@vQa1#FNJ`i1M!fz6#2;qkDQ33JMF&2VS$xwD<`2#W7rb^_`uaLF>WCIGCE4+)_9qlfE025*7JLP2zKdu{So+fV`HOLFfDMS-@o0)iLa&8W39M**3Ad3$ej zzP@tUzGy03Ifw9Ji4NSMG5Wc?e zrkoKA`xzWm27_&VIBu-03o|wg@j*^BXulSWC#vbgcU_Jx!Iw`4|p4EH+JUISNx` z5j@Hi4 zqM)Dvj!|nT@uuse92oh5y!<_fnJOiF*W_R77E~48<2FJw)s|Smyfi`BXH$+d>xm>8 z`26|7&GpsFcbyx`{lmks>};mM%LC={CMsSdWO_QCGR3P74NS?&em99x!VWSXneusV zQ8BSx`{|0J6Mg%?TyUnt@uUj}QVekH-F{jjYc z{Y#$=Qc_Z=1)gL7H9pScwK8Xz%4-aDeE4(0gYy_VJ(@O!O_u>`)U~DzBOQFu$ z)daBt8NsQE_%keW0AdX4wBVtzQK=Jp5IouC!goWH$oTEC`Gtr@12G#8ZytAhouDbb zgjQfkJek})lretu*mM@(YkYu2j$=cO?0{fuJ zRrO+svb6G|K$$aX^6{*Q;A%W%ELzmI{if%MuI}V!rVi~Bef>yaAr`=qP}!KLuClzm z7o=FmS_M0FgQY{M7gj0T=h3xiko)QSXZ@D*8Uzj%ykl^Zbv@umZ8VJ#QgIG1Qoi%k`yC$q+Ls zLA-2~3b}79qxDFJ?eCXU3XTi_sT6VnAc2JRPe5vRQ59e?9K2jDFC-*Y*3^8x>`4Ge z|Fv)j6GHekt(mCOKsg`lBXXL*NUHHnob$`73gGpt7{h9@A_y5sTbyj4VcvII!h`h1 zz2SAg#IPa6S_;+j%80YcE<>{mn1DbUzMP!g>%r&RsSnt38G``;$(ndU9Q9H;M}Zx; zTrXPKeri83=X(_Zb#~lVlX!p(xW26>TiTHdoxDb@dH0{seX<=G9874!$H2st`m0rs z0S30Vm|$>luoEPBK#m>YKGGD zK0HIpj}jg#_qSO>95o-K+hKz=vZ{huR&X|#(uV5|m0SFGvEMQh7H8}}Spi^raG z@BR+4)H&sm+9e9@fmi&%5kM8x(ckap{W3Zl@A`5>rh72T^?>$E(4}AHeU|>KC zB8ir!CbFeP(*JBd^)0_S+H-+F&dvazMG^bVtE;OhWQsb@IkNZ%`yT!r2fPRK_VxxD z3LWs!OAr{dg06udx$B>BBfF^_+ZXc$mgn!zJ5RrfQDSp*a|7O7$XjUq`|wb~-(S+{ zTT2uO{cMtwEo0x1Ac$BV@64Va&pW%Wf2N3Gl40y%S~&ycg$}jdT>CXoEm67L-ls z)6sRUa5Wv4a0H1{mg?dp;QvWOVZu4s1&<0se{j_3DYCVRTv9-RCb}u-v;x0mQM04XnAENcz@po3|0O88#=drPe5$8 zb9D2Sa_&C?m-5k8;&2S36s_OMuW+zNaL6RIw66d;8+xiY?(8@yC@HN1>@9jhLqmf< zYQ- zCHX;a2kKv%Rry1VAWD&vkpbsTNJt1iSnFq#Svt4R0%-p_BO^vS;QZ|y0!B&dv9U3W zetU-Bt5qNE0Lpfaa9#f5+HPw#gk8 zHzyyouWxzW6NRNePc7CS^b>JUPdzUCnp6BGa$&)L;9cXPBK}lNS$T1>?DOaBgiO-- zu}b3(^T4zXQ>>m)=uQ^(D|%m3s|7SK-~T*RkY-w4l0OLWn@Y;>SmDJB4y)mJ;egmm z>(7>vxxLX;mLNk%#>Mr$;W6CLzPZFY`IQ!AIKF)pa=i#PhvA2MiscTb@P`$dMy!Y; zbXht=sH+Of(y4E^gsi&by?Qi++OiwW> zN)Id^#j}mJ-wag1((0vb0M##msQiA%4$;O9cl64t zbZzhJYU#%IeAj_GL?Uit(Qne>&?(CmmW{Z|c(_F1CE~fYbvlndc1OU)@w0%7h97_j z!IVvct~^0LVi6Uk29>X%6cs6Hh-H6VZNv4;dsJ~q*w%8L!z`M$wKee4Wx&AH_bf0H zlai{`!glHzc#vC<1011JjzNFdf8ePJD8}dJ3;^$S*$6!-oqTXB=@~ur zAlBU#4nHYtr%0nt{(Zh%ulH{xn&<+U(y-nsT&=JRu-x6ccu-)8O9r3AB7jgdFfdT1 z+8P%In|>UV4yJ| z@{_zOTUzKr0r9cvs(G(18h|4!FYm|)m~u8y3-XgUzRuMDMJP;>^XJEK=$MVrg*ig{ zos&t&+qSx;ie_AdRnBg`dfeXe?mRXg-WtCA{SL@6;?3P>X!&E2py*aNR%_;e0WGh6 z^G|;{*0|jkh$wKh{DF@?vGa^G*v@XpZ?P&LU{%z^63B!R3sI8pG|n$x|7p&@D7Q~R z5z2Km+s`*BSMv20pV+eU$|xqVM3T-1r_!EQMj^B7_Z_*`JMh?$TCI*xQ{MtD3y>_q ze`{H@QQ*cu&zaqrb8J>P`DU>68D{I8jP;C-V{ONaa+~HpM;k=VQO9+0)UY*@@mDkP zOH!XozYh%iwWsk#H76PU>I%u}2a}TM{zcYDru7FP7^%w>7}oQ4cDo z*MP30@eO)cT)sxa1+J7%TC8-1XW&iug@lA)lmijMWy9n))Gm2 zJ`pOTDBVt;kU^Z?ruDBHT!)1=DyYii7rw)yJ2AB1cZW~K%f7BI&bZ+p!tTGQ_W(`L zO>?K~?~Lyc$`$QYId}2!rWsMIZef z@BdpAEinhC_`q5NmQNDZ)!T~+M26HReAcllpiKVX>&ISCo;(RnHSxuf z@;yXGL|_4JAR5%a>c*4_n;`P<17yhuwdm$_B@>_pPEXYk;0lB&u`MGbqY5Pr4keJI zC+{d#PP6gz6N3od-RgI;zw>d_qA!Lsrs^x6W3xL_3AjcQ-#;OPb!aMzu z?p)=xDBjT2wAxE$8U{G+QHCgsr)`LWva;oBPn2ef&flM}(}JUOKUfo>kCT-1mXulj!VNb3n=WiyM5Tn!Nf>IpKzrQ{%>=KgqH`%~aIYQ5uwkGNg0I)eqES&5a=Qf-ziv ze^*8L_{imt$>xtO1Kie5ReGMM)y%r}bBuBx^TNBIEcD`8?eOk={TdLW_m7YJu$cUj zpz!+aBtpX^$ci6m+^p{)vYmEMvyqFZ&JfHV(6a0Kp>0o3PsijW1rT{_6iXcAzJUGZ z5n*GsGrhhDdbE03m`xY(Xg#kddqW26vG>8K$AID7Msj%Ii1d(rhg8aGVRs)Gw z#fM!G6>4cc;plcpu|XYCJG-;4;8<3sHr)kp#X1Or`~?C6iI^86fAq}bch~nZ`5mJK zOEaW)>A~9i_Nhz1^!IPviNJgs8o2KHZRtxQiUMV`W$}0D*i|*+E%fzG!wwGx4R3k7 zb?uZ`u9Ph!v{|TgCb%bP@I|i|Z{(hqDsws$l?<_ zAR(eOhYU#{Qs>qqpnEq!0IcpltHE$?zp9({0x>ea{c6`)G~it5^Ux3pF)@RvRvGDN$Wsn{nj^FV?w{-u#%+;VnI#31m>zxVP!>wa>jq6#zi6_a7C_k z64fdI^^<7eWy9>4m5~v>UYUOI#DvcH(F?#Tnx&Ig!aBOT=3jHLY0B>A`_H zArKSU?hnDXwfOw`S{S`<-$$E2=Fve{+442db1Oz^XW_zG$KJk*-M2}1I+sLizHrRr zbrVLqIZ}<8pa1KQH(%v>+Cxxko@pBL@$rrCwgsO5#aUQfTmc(Z|IHT zWV(|g=g8s37~kD|qTh(vY&zcTcN2jROxdJ6EjFdiJ$fgEBXe~~W)g6ui&7=JyU~HE z16>+4b1G*K4S_<$_+vCX9<&bDK=4AfjeuuFq8bxmr}cK9Dk`Qd^DYSfOcPDYx@}|3 zY9}!huAaC#SxSXGub9OlyCpP#3~ZzUali^Pe6;sBpZ=Z3A~+`KnOL0tUe|B)7X!ig z*5j<0;dBwp_0K6G&7M(_^c3iy2+}|S-{kQ#gh=`na{uuqxW2xA_Rr+x0LA4!W7)-&+0HBqZo0ymn+kNe2od^EoFwJ8nuIgRtUauESr8bhNQ>P>7?ps>;0k zYqPg==~j}2*t139q=dBC#2Va(^fcxNPLv7?`r%Xivp6|s~V=K6-&s^icy?wWzFfBBwF^}+p?;p@O%>QX!Wt#`6oa( zi^MSho7}ieO-2gZ^0PGm(SrW}uXq2y|Ng=94NL)pZ8}(Gy&8P^0#a3cq)_p|Eablc D Date: Tue, 9 Apr 2024 20:12:21 -0400 Subject: [PATCH 34/60] links to aer topic, runtime primitives intro topic --- docs/verify/simulate-with-qiskit-primitives.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 16e412a8d90..46e28cbddda 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -6,7 +6,7 @@ description: How to perform exact simulation of quantum circuits using primitive The reference primitives in Qiskit perform local statevector simulations. These simulations do not support modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation -techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives). +techniques ([using Qiskit Aer](/verify/stabilizer-circuit-simulation)) or running on real devices ([Qiskit Runtime primitives](/run/primitives)). The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample from output distributions of circuits. @@ -20,7 +20,7 @@ simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.Stateve [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the -legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally +legacy Estimator V1 interface. (For more information, see the [V2 primitives migration guide](/api/migration-guides/v2-primitives).) Both can take circuits, observables, and parameters as inputs and return the locally computed expectation values. The following code prepares the inputs that will be used in the examples that follow. The expected input type for the @@ -202,7 +202,7 @@ the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) c [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the -legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from +legacy Sampler V1 interface. (For more information, see the [V2 primitives migration guide](/api/migration-guides/v2-primitives).) Both can take circuits and parameters as inputs and return the results from sampling from the output probability distributions, but they are expressed in different terms: - The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or "counts" From 8dae5ac7fea72ad5ecebf97024803363385d437a Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Wed, 10 Apr 2024 10:32:22 -0400 Subject: [PATCH 35/60] should be sampler in a sampler example --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 46e28cbddda..e6ce943185c 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -414,7 +414,7 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. ```python - job = estimator.run(qc, observable, shots=2048, seed=123) + job = sampler.run(qc, observable, shots=2048, seed=123) result = job.result() print(result) ``` From 50101bbf8dfcbe9b2b3e8f2f31abf4ebf732e8a0 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Wed, 10 Apr 2024 15:08:58 -0400 Subject: [PATCH 36/60] add transpilation instructions to sampler section --- .../simulate-with-qiskit-primitives.mdx | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index e6ce943185c..75ed92f6f75 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -195,6 +195,8 @@ instead of the number of `shots` used in the V1 interface. +See more examples on the [Primitives examples](/run/primitives-examples#estimator-examples) page. + ## Use the reference `Sampler` Similar to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`: @@ -257,8 +259,14 @@ sampler = Sampler() ```python + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit = pm.run(circuit) + # execute 1 circuit with 3 parameter sets using Sampler V2 - job = sampler_v2.run([(circuit, [vals1, vals2, vals3])]) + job = sampler.run([(isa_circuit, [vals1, vals2, vals3])]) counts = job.result()[0].data.meas.get_counts() ``` V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result. @@ -266,8 +274,15 @@ sampler = Sampler() which was not always possible in the V1 interface: ```python + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit1 = pm.run(circuit1) + isa_circuit2 = pm.run(circuit2) + # execute 2 circuits with 1 parameter set using Sampler V2 - job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)]) + job = sampler.run([(isa_circuit1, vals1), (isa_circuit2, vals1)]) counts1 = job.result() counts2 = job.result() ``` @@ -280,7 +295,13 @@ sampler = Sampler() with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python - job = sampler.run(qc) + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit = pm.run(circuit) + + job = sampler.run(isa_circuit) result = job.result() print(result) ``` @@ -361,8 +382,14 @@ Negative quasi-probabilities may appear when using error mitigation techniques. ``` ```python + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit = pm.run(circuit) + # Run using V1 sampler - result = sampler_v1.run(circuit).result() + result = sampler_v1.run(isa_circuit).result() quasi_dist = result.quasi_dists[0] print(f"The quasi-probability distribution is: {quasi_dist}") ``` @@ -396,12 +423,19 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev ```python + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit1 = pm.run(circuit1) + isa_circuit2 = pm.run(circuit2) + # Sample two circuits at 128 shots each. - sampler_v2.run([circuit1, circuit2], shots=128) + sampler.run([isa_circuit1, isa_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_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) + sampler.run([(isa_circuit1, None, 123), (isa_circuit2, None, 456)]) ``` @@ -414,13 +448,20 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. ```python - job = sampler.run(qc, observable, shots=2048, seed=123) + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit = pm.run(circuit) + + job = sampler.run(isa_circuit, observable, shots=2048, seed=123) result = job.result() print(result) ``` +See more examples on the [Primitives examples](/run/primitives-examples#sampler-examples) page. ## Next steps From ae566fb75f57de872b6a9f17f16cd129292bf65f Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Wed, 10 Apr 2024 15:19:50 -0400 Subject: [PATCH 37/60] add in isa transpilation for estimator section --- .../simulate-with-qiskit-primitives.mdx | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 75ed92f6f75..6fe7a8ddfca 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -93,7 +93,13 @@ observable. with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method. ```python -job = estimator.run([(qc, observable, parameter_values)]) +# Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + +pm = generate_preset_pass_manager(backend=backend, optimization_level=1) +isa_circuit = pm.run(qc) + +job = estimator.run([(isa_circuit, observable, parameter_values)]) result = job.result() print(f" > Result class: {type(result)}") ``` @@ -108,7 +114,13 @@ print(f" > Result class: {type(result)}") with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python -job = estimator.run([qc]*3, [observable]*3, parameter_values) +# Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + +pm = generate_preset_pass_manager(backend=backend, optimization_level=1) +isa_circuit = pm.run(qc) + +job = estimator.run([isa_circuit]*3, [observable]*3, parameter_values) result = job.result() print(f" > Result class: {type(result)}") ``` @@ -174,8 +186,15 @@ instead of the number of `shots` used in the V1 interface. method level. This allows for a more finely-grained tuning of the option all the way to the PUB level. ```python + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit1 = pm.run(circuit1) + isa_circuit2 = pm.run(circuit2) + # Estimate expectation values for two PUBs, both with 0.05 precision. - estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05) + estimator.run([(isa_circuit1, obs_array1), (isa_circuit2, obs_array_2)], precision=0.05) ``` @@ -188,7 +207,13 @@ instead of the number of `shots` used in the V1 interface. - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. ```python - job = estimator.run(qc, observable, shots=2048, seed=123) + # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + isa_circuit = pm.run(qc) + + job = estimator.run(isa_circuit, observable, shots=2048, seed=123) result = job.result() print(result) ``` From 98f49564877ff0f1f581482acf92065efef0735b Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Wed, 10 Apr 2024 16:16:03 -0400 Subject: [PATCH 38/60] add output --- .../simulate-with-qiskit-primitives.ipynb | 616 ++++++++++++++++++ .../simulate-with-qiskit-primitives.mdx | 9 + 2 files changed, 625 insertions(+) create mode 100644 docs/verify/simulate-with-qiskit-primitives.ipynb diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb new file mode 100644 index 00000000000..94963515875 --- /dev/null +++ b/docs/verify/simulate-with-qiskit-primitives.ipynb @@ -0,0 +1,616 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exact simulation with Qiskit primitives" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", + "modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation\n", + "techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives).\n", + "\n", + "The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample\n", + "from output distributions of circuits.\n", + "\n", + "The following sections show how to use the reference primitives to run your workflow locally." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use the reference `Estimator`\n", + "\n", + "There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector\n", + "simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the\n", + "[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator)\n", + "implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization\n", + "features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the\n", + "legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally\n", + "computed expectation values.\n", + "\n", + "The following code prepares the inputs that will be used in the examples that follow. The expected input type for the\n", + "observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that\n", + "the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits.\n", + "\n", + "\n", + " Any circuit passed to an Estimator must **not** include any **measurements**.\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAATEAAACuCAYAAABeIjpKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAAATOElEQVR4nO3de1hVZb4H8O/a3MGNcsutooACiihYIomajY46mGjOlLcxtR473fTRmcztk6fL2JmTUT6ZjuVoM2lNHcK0i8pkWXjhmBFEjgoohoDcdroFRAG37Mv5g5ETsRE2rn15F9/P8/Qka73rfX/uR757rXe/ay/JYrFYQEQkKJWzCyAiuh0MMSISGkOMiITGECMioTHEiEhoDDEiEhpDjIiExhAjIqExxIhIaAwxIhIaQ4yIhMYQIyKhMcSISGgMMSISGkOMiITGECMioTHEiEhoDDEiEhpDjIiExhAjIqExxIhIaAwxIhIaQ4yIhMYQIyKhMcSISGgMMSISGkOMiITGECMioTHEiEhoDDEiEhpDjIiExhAjIqExxIhIaAwxIhIaQ4yIhMYQIyKhMcSISGjuzi6A2rNYLDA2GZxdhk3cfbwgSZJs/VksFsAg1msAL3lfA+oahpgLMjYZ8MGQh5xdhk0WFr8PD19v+To0GGCcu0S+/hzAfde7gLeMrwF1CS8niUhoDDEiEhpDjIiExhAjIqExxIhIaAwxIhIaQ4yIhMZ1YgqiSYpF8sfr2mxrbmhC/flqFO8+isK//xMWk9lJ1RHZB0NMgc5/nIWKzDxAkuAT0geRc+5F4rqH0TtqAI6v3ubs8ohkxRBToMunSnB+T1brz2d3foHfZm1C9O9/jbxX0mC4XO/E6ojkxTmxHsDYZMClvHOQVCr4h/V1djlEsmKI9RDq8JbwMtRdc3IlRPLi5aQCuft4witQ3TonNnTxNASNHIxLeedQf77a2eURyUrxZ2J6vR5arRaRkZHw9vbGwIEDsXLlSjQ0NGDp0qWQJAlbtmxxdpmyulM7Hwvyd2DB6Xcw+9DriHkkGaUZ3yLz4VRnl0ZOdKakDhlHL2DvoTLknL4Es9ni7JJkoegzsRMnTmD69OnQ6XTw8/PD8OHDUVVVhc2bN6O4uBg1NTUAgFGjRjm3UJmd/ceXKN13HCoPdwQMG4QRy2bDr18QTIYbrW3u3fpHQCXhyOOvt27z7NMLsw9vRO5L7+H8x1nWuhbOEf1FTD1+GK8Mj8PTQ4ZZbeO5bxfuu6MfPr37HgdXZ38mkxnpB0rw1q5CHPvhpzb7osL88eTcGDz6u2io/TydVOHtU+yZmF6vx8yZM6HT6bBq1SpUV1cjLy8POp0OqampyMjIQE5ODiRJQlxcnLPLlVX9eR2qs06hMvMHnH7rM3y95BUEjxqCpNTHW9scf/Zt3DFmKCJmj2/dNvblR3HxuzOKCbCe7rrBiDnPZGLhs4fbBRgAnCurx9OvZWPCkgxU/tTghArlodgQW7FiBSoqKrB8+XJs2LABarW6dZ9Wq0V8fDyMRiPCw8Ph7+/vxErt71LuWRTvPoqI2eMRkjAUAHCj7hq+WbUVd//3o/DpG4CwGWOhGReL42u4jkwJzGYLFq09gk++Luu07cmiGvzmiQOoqxfsm3T/TZEhVlhYiPT0dAQHB2P9+vVW24wePRoAEB8f32Z7SUkJZs2aBbVajYCAACxevBiXL1+2e8329q+Nu2E2mnDn6nmt2yoPnUDpvm8wccsKjH3lP/DNqq0w1PLTSyX44lgFdh8s7XL7/OI6bPog334F2ZEiQywtLQ1msxkLFy5Er169rLbx8fEB0DbErl69ikmTJqGiogJpaWnYvn07srKykJKSArNZ7Nt1rpbqUPLZMfSfGIc77o5p3Z677j2oIzSozPwBFV/nObFC+2o0maA3GKz+p0RvpRfafMz2PWfR3Czev3NFTuxnZmYCACZNmtRhm4qKCgBtQ2z79u2orKzE0aNHMWjQIABAaGgoxo0bh71792L27Nn2K9oBTm7ag4jZ43Hn6nn44sE/AWhZCHut7CJqCy84tzg7e+lsPl46K+aZhq0uXm5CRla5zcdVXWzE19lVSJ4Qaoeq7EeRIVZW1jIPEBYWZnW/0WjEsWPHALQNsf3792PChAmtAQYASUlJGDx4MPbt29ftEEtISIBOp+tyew+LCi8i0eZxdMfzsbPfgx3uv3KuEu+Fzutw/+2IjopGsyTfu7iPSoWCUUmy9ffooMF4oP9Aq/umf3tEljGio6PR5AJn7DfcNLD0frJbxy5Ysgx+hu9lrqhzGo0Gubm53TpWkSHW0NDySUtTU5PV/enp6dDr9VCr1YiIiGjdXlBQgDlz5rRrHxsbi4KCgm7Xo9PpUFlZ2eX2npIbINjdQVXVVbhhMcnWn6+bGzBKtu4Q2asXfh1i3xe1qqoKjSb5XoNu85aA3t07tK62FnW1Xf+36goUGWIajQa1tbXIy8tDUlLbd/Pq6mqsXr0aABAXF9fmOYG1tbXo06dPu/4CAwNx9uzZ26rHFh4WFeD8N3Sb9O/XX/YzMdH079/fJc7ETJIPdBYzINn+Ggb1luDtO8AOVd2arb8jP6fIEJsyZQoKCwuRmpqKqVOnIjo6GgCQk5ODRYsWQa/XA3DcIldbT5ObG6879LmTBx548bb7KDpXJOtzJy3Xrwv33MmioiJILvLcyftXHMTew7bNcw64wxeleYfg7i7WG4hY1XaRVqtFUFAQysvLERsbi5EjRyIqKgqJiYkYPHgwJk+eDKD98oqAgADU1dW166+mpgaBgYGOKJ1IFk/Ni+m80S88PmeYcAEGKDTEQkNDkZWVhRkzZsDb2xulpaUIDAzEtm3bkJGRgaKiIgDtQywmJsbq3FdBQQFiYmz/R0HkLFOTBmB+8uAut4+LDsTKhbF2rMh+FHk5CbQE0v79+9ttv3btGkpLS6FSqTBixIg2+1JSUrB27VpUVFQgNLTlY+bs7GwUFxfjtddec0jdRHJQqSTs/PNEmC0W7Pqi5JZt7xwWhIw3p8G/l5j3T0oWi0UZt7J3UXZ2NsaOHYuhQ4fizJkzbfbV19dj5MiRCA4Oxrp163D9+nVotVqEhITg+PHjUDlostnRc2JyWFj8fo+fE3Pf9a7LzIndZDZbsOerUryVXojDOW2/hmn4kD54al4MHp4VBT9fDydVePsUeybWkVOnTgFofykJAP7+/sjMzMTKlSsxf/58uLu7IyUlBRs3bnRYgBHJSaWSMGdaBOZMi8C5sitIemgfLl8xICTAG6c//l2bT+dFxRD7hSFDhli9DHVFo1bNxaktn8BkaMaEN5ahJr8UBW9n2NTHoOQxaLpYh0t55+xUJbmKqLDe8PZyAwB4eqgUEWCAQif2b6WzEBPJqGfmws3r9i4DBiUnImR0tEwVETlejzsTu3lfpeiSUh8DAEz/9L9gMZnR+FMtekcNwLRdL8KvfxDqzpbjyBMbYW42QnJ3w13a+dBMGAE3D3dcOV+N49ptCBkdjYHTEtBvYhwi5/4KhTsOoOLg95i49Q/wUPvAzcsTumOnkf3cO0DPmjolgfS4EFOK42u2Y+jiafh89vO4Ud+ICW8sQ2BsBA48+CLMBiOSP3kJYTPuRsmnxzDiqfvR3GRAxn3PAgDi/vgg7lyzANlr/4byL3PbXIa6eXng68WvwNh4HZJKhck71yBi1jiUfHbMmX9dog4xxBTkwufZMDW1fAW1/sSPUIe33MoxKHkMPNW+CL/vbgCAytMd18ovWe9EJWH0cw+hb+KwlgeNBPuj7swFhhi5LIaYgpgMza1/tpjMULm1TOJKkoTs595B1ZF/ddpH7OMz4RPcGxkznoXJ0Iwxf1oCN29xP34n5etxE/tKcuNqIzz8fTttd+HAdxj+WArcfFoWM7r5eKJPdOi/+2iCh/r/+/Ds7Yemi7UwGZrhE9IH4SnyfR0OkT3wTExg+X/dh2kfvgBTkwGNP9V22O7Ulk8R/7QHUjLWt87Pn37zU9QVVaB49xFM2LQcg5ITcWbnART+7Z/41durcP/hjWjS1aAq66SD/jZE3dPjVuyLgCv2uWLfXkKnpKHyYiMG3OGLiq8WOLscWfBykoiExhAjIqExxIhIaAwxIhIaQ4yIhMYlFi7I3ccLC4vfd3YZNnH38ZK3Qy8vuO96V94+7c1L5teAuoQh5oIkSZJ1uYKIJEkCXHy5ArkGXk4SkdAYYkQkNIYYEQmNIUZEQmOIEZHQGGJEJDSGGBEJjSFGREJjiBGR0BhiRCQ0hhgRCY0hRkRCY4gRkdAYYkQkNIYYEQmNIUZEQmOIEZHQGGJEJDSGGBEJjSFGREJjiBGR0BhiRCQ0hhgRCY0hRkRC48NziRSs6boRJ4tq8H2BHifP1aLmigEAUFtvwGs7TmL08GDcFROEPv7iPr1cslgsFmcXQUTy+r5Ajzc/LEDa5+dx3WC6ZVtJAu67ZyCemheD5PGhUKkkB1UpD4YYkYIUlV7BYy/9L47k6rp1fFSYP7Y9Px6TEvvLXJn9MMSIFMBstmDTB/lYuzm30zOvrnhy7jC8+nQievl6yFCdfTHEiATX3GzG4v88gg8PnJe137tignBg628QEugja79yY4gRCcxkMmPBmsP46MsSu/Q/MioAR3bMQIALT/xziQWRwJ7fkme3AAOAU+dqMfeZTLjyuQ5DjEhQ2ScvInXHSZuOyUmbhfKD85GTNqvLx3z1bRW2fXTG1vIcpkeEmF6vh1arRWRkJLy9vTFw4ECsXLkSDQ0NWLp0KSRJwpYtW5xdJlGXGW6Y8MgLWTCbbTtD0gT7IrSvHzTBvjYdt/r1HJRVXbXpGEdR/GLXEydOYPr06dDpdPDz88Pw4cNRVVWFzZs3o7i4GDU1NQCAUaNGObdQIhvsPliCwvN1DhvvWmMzNv4jH2+sGeuwMbtK0Wdier0eM2fOhE6nw6pVq1BdXY28vDzodDqkpqYiIyMDOTk5kCQJcXFxzi6XqMveSi90+Jg7955DQ2Ozw8ftjKJDbMWKFaioqMDy5cuxYcMGqNXq1n1arRbx8fEwGo0IDw+Hv7+/Eysl6rpTRTX45sRFh4975eoN2ZdxyEGxIVZYWIj09HQEBwdj/fr1VtuMHj0aABAfH9+67WboJSYmwsvLC5Ik1i0YpHyHcqqdNvbhXOeN3RHFhlhaWhrMZjMWLlyIXr16WW3j49OyiO/nIfbjjz9iz5490Gg0GDNmjENqJbLF9wV6J4592Wljd0SxIZaZmQkAmDRpUodtKioqALQNsYkTJ6K6uhp79+7FlClT7FskUTf8cMZ5QXKmpM7l5sUU++lkWVkZACAsLMzqfqPRiGPHjgFoG2Iqlfy5npCQAJ2uezfkEv1SdZ9nAJXa6r6ctFm3XD6hCfZp/X/5wfkdttPpGzFmwd522y0WYMiweLib622s+tY0Gg1yc3O7daxiQ6yhoQEA0NTUZHV/eno69Ho91Go1IiIi7FqLTqdDZWWlXcegHsQfHV5D3VwH1hl3N1WX2lnzk+4S0Oy8S9pfUmyIaTQa1NbWIi8vD0lJSW32VVdXY/Xq1QCAuLg4u0/eazQau/ZPPUu1ygJzB/t0+sZbHqsJ9oG7mwpGkxk6vfU3+M760fQNhptF3nspb+d3RLEhNmXKFBQWFiI1NRVTp05FdHQ0ACAnJweLFi2CXt/yTuKIRa7dPU0msibpob349uQlq/usXQL+XPnB+Qjt6wedvgkDp35o89henm64cD4fHh6uM53uOpXITKvVIigoCOXl5YiNjcXIkSMRFRWFxMREDB48GJMnTwbQdj6MSASjhwc7bez46ECXCjBAwSEWGhqKrKwszJgxA97e3igtLUVgYCC2bduGjIwMFBUVAWCIkXicGWKjhwc5beyOKPZyEgBiYmKwf//+dtuvXbuG0tJSqFQqjBgxwgmVEXVf8vhQuLtLMBod//U4KfcOcviYnVF0iHUkPz8fFosF0dHR8PVt/3H07t27AQAFBQVtfg4PD0dCQoLjCiWyol+IL347Odyu3yNmTcQANZLHhzp0zK7okSF26tQpAB1fSs6ZM8fqz0uWLMHOnTvtWhtRVzw1L8bhIfbEnGEu+SQkhpgVrvwtlkQAcG+CBjPvHYR9Ry44ZLwhA9VYNj/GIWPZSrET+7fSWYgRuTpJkrDthfHoo/Z0yHjvrLsHfi765KMeeSZ2875KIpH1C/HFX58fj/naQ10+5uYi1s4Wxf7cM0tGYmJCP5vrcxQ+7YhIcJveP40/vJptl74XpURi558nuuRc2E0MMSIF2PbRGSx7+RuYTPL9Oj85dxj+8mwS3Nxce9aJIUakELn5l/DI81k4/WPtbfUTEuCNrc+NwwNT7fvFCHJhiBEpiOGGCa/uOIm//E8BLtVet+lYby83LEqJxMsrEhAc4G2nCuXHECNSIMMNE/YcLMXfPzmL707rca2DLzL0cFchfmggfn/fEDx8f5RLP+m7IwwxIoUzmy0oKruCk0U1uNrQDLPZAl8fdwyL6IMRkQHw8nRzdom3hSFGREJz7Y8diIg6wRAjIqExxIhIaAwxIhIaQ4yIhMYQIyKhMcSISGgMMSISGkOMiITGECMioTHEiEhoDDEiEhpDjIiExhAjIqExxIhIaAwxIhIaQ4yIhMYQIyKhMcSISGgMMSISGkOMiITGECMioTHEiEhoDDEiEhpDjIiExhAjIqExxIhIaAwxIhIaQ4yIhMYQIyKhMcSISGj/Bx+h7EZ8qyzWAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "from qiskit.circuit import Parameter\n", + "from qiskit.quantum_info import SparsePauliOp\n", + "\n", + "# circuit for which you want to obtain the expected value\n", + "qc = QuantumCircuit(2)\n", + "qc.ry(Parameter('theta'), 0)\n", + "qc.h(0)\n", + "qc.cx(0,1)\n", + "qc.draw(\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# observable(s) whose expected values you want to compute\n", + "observable = SparsePauliOp([\"II\", \"XX\", \"YY\", \"ZZ\"], coeffs=[1, 1, -1, 1])\n", + "\n", + "# value(s) for the circuit parameter(s)\n", + "import numpy as np\n", + "parameter_values = [[0], [np.pi/6], [np.pi/2]]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize an Estimator\n", + "\n", + "To use the Estimator V2 implementation, follow the instructions to instantiate a\n", + "[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain\n", + "your pre-existing workflow using an Estimator V1 implementation, you can also use the\n", + "[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class.\n", + "\n", + "\n", + " \n", + " Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator).\n", + "\n", + "```python\n", + "from qiskit.primitives import StatevectorEstimator\n", + "estimator = StatevectorEstimator()\n", + "```\n", + " \n", + "\n", + " \n", + " Instantiate a [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator).\n", + "\n", + "```python\n", + "from qiskit.primitives import Estimator\n", + "estimator = Estimator()\n", + "```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run and get results\n", + "\n", + "This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one\n", + "observable.\n", + "\n", + "\n", + "\n", + " \n", + " Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run)\n", + " method, which returns an instance of a [PrimitiveJob](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the\n", + " job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object)\n", + " with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method.\n", + "\n", + "```python\n", + "job = estimator.run([(qc, observable, parameter_values)])\n", + "result = job.result()\n", + "print(f\" > Result class: {type(result)}\")\n", + "```\n", + "```text\n", + " > Result class: \n", + "```\n", + " \n", + " \n", + " Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method,\n", + " which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the\n", + " job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object)\n", + " with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", + "\n", + "```python\n", + "job = estimator.run([qc]*3, [observable]*3, parameter_values)\n", + "result = job.result()\n", + "print(f\" > Result class: {type(result)}\")\n", + "```\n", + "```text\n", + " > Result class: \n", + "```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Get the expected value from the result\n", + "\n", + "\n", + " \n", + "\n", + " The primitives V2 result outputs an array of [`PubResult`s](/api/qiskit/qiskit.primitives.PubResult#pubresult), where each item of the array is a `PubResult` object\n", + " that contains in its data the array of evaluations corresponding to every circuit-observable combination in the PUB.\n", + " To retrieve the expectation values and metadata for the first\n", + " (and in this case, only) circuit evaluation, we must access the evaluation [`data`](/api/qiskit/qiskit.primitives.PubResult#data) for PUB 0:\n", + "\n", + "```python\n", + "print(f\" > Expectation value: {result[0].data.evs}\")\n", + "print(f\" > Metadata: {result[0].metadata}\")\n", + "```\n", + "```text\n", + " > Expectation value: [4. 3.73205081 2. ]\n", + " > Metadata: {'precision': 0.0}\n", + "```\n", + " \n", + " \n", + "\n", + " The primitives V1 result stores an array of values that can be accessed through the attribute\n", + " [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th\n", + " element is the expectation value corresponding to the `i`th circuit and `i`th observable.\n", + " To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array.\n", + "\n", + "```python\n", + "print(f\" > Expectation value: {result.values[0]}\")\n", + "print(f\" > Metadata: {result.metadata}\")\n", + "```\n", + "\n", + "```text\n", + " > Expectation value: 3.999999999999999\n", + " > Metadata: [{}, {}, {}]\n", + "```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set Estimator run options\n", + "\n", + "By default, the reference Estimator performs an exact statevector calculation based on the\n", + "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", + "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", + "\n", + "With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined.\n", + "The new interface accepts a `precision` argument that expresses the error bars that the\n", + "primitive implementation should target for expectation values estimates,\n", + "instead of the number of `shots` used in the V1 interface.\n", + "\n", + "\n", + " \n", + "\n", + " The sampling overhead is now called `precision`, and is defined exclusively at the `.run()`\n", + " method level. This allows for a more finely-grained tuning of the option all the way to the PUB level.\n", + "\n", + " ```python\n", + " # Estimate expectation values for two PUBs, both with 0.05 precision.\n", + " estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)\n", + " ```\n", + "\n", + " \n", + "\n", + " \n", + "\n", + " The V1 interface specifies shots in the following ways:\n", + "\n", + " - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.\n", + " - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.\n", + "\n", + " ```python\n", + " job = estimator.run(qc, observable, shots=2048, seed=123)\n", + " result = job.result()\n", + " print(result)\n", + " ```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use the reference `Sampler`\n", + "\n", + "Similar to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`:\n", + "the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the\n", + "[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler)\n", + "implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization\n", + "features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the\n", + "legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from\n", + "the output probability distributions, but they are expressed in different terms:\n", + "\n", + "- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or \"counts\"\n", + " for each bitstring present in the output distribution.\n", + "- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states.\n", + "\n", + "The following code prepares the inputs used in the examples that follow. Note that\n", + "these examples run a single parametrized circuit, but you can also run the Sampler\n", + "on non-parametrized circuits." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "\n", + "qc = QuantumCircuit(2)\n", + "qc.h(0)\n", + "qc.cx(0,1)\n", + "qc.measure_all()\n", + "qc.draw(\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Any quantum circuit passed to a Sampler **must** include measurements.\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize `Sampler`\n", + "\n", + "To use the Sampler V2 implementation, follow the instructions to instantiate a\n", + "[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain\n", + "your pre-existing workflow using a Sampler V1 implementation, you can also use the\n", + "[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class.\n", + "\n", + "\n", + " \n", + " ```python\n", + "from qiskit.primitives import StatevectorSampler\n", + "\n", + "sampler = StatevectorSampler()\n", + "```\n", + " \n", + "\n", + " \n", + " ```python\n", + "from qiskit.primitives import Sampler\n", + "\n", + "sampler = Sampler()\n", + "```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run and get results\n", + "\n", + "\n", + " \n", + " ```python\n", + " # execute 1 circuit with 3 parameter sets using Sampler V2\n", + " job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])\n", + " counts = job.result()[0].data.meas.get_counts()\n", + " ```\n", + " V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result.\n", + " Therefore, you can run different circuits with various parameter/observable combinations,\n", + " which was not always possible in the V1 interface:\n", + "\n", + " ```python\n", + " # execute 2 circuits with 1 parameter set using Sampler V2\n", + " job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])\n", + " counts1 = job.result()\n", + " counts2 = job.result()\n", + " ```\n", + " \n", + "\n", + " \n", + " Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)\n", + " method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1).\n", + " You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object)\n", + " with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", + "\n", + " ```python\n", + " job = sampler.run(qc)\n", + " result = job.result()\n", + " print(result)\n", + " ```\n", + "\n", + " ```python\n", + " SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}])\n", + " ```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get the probability distribution or measurement outcome\n", + "\n", + "As mentioned above, the result retrieval step is different between V1 and V2 interfaces.\n", + "\n", + "The V1 sampler gives access to quasi-probability distributions.\n", + "\n", + "The V2 sampler returns measurement outcome samples in the form of **bitstrings** or\n", + "**counts**. The bitstrings show the measurement outcomes, preserving the shot\n", + "order in which they were measured. The V2 sampler result objects organize\n", + "data in terms of their input circuits' classical register names, for\n", + "compatibility with dynamic circuits.\n", + "\n", + "\n", + "\n", + " \n", + " The name of the classical register defaults to `\"meas\"`.\n", + " This name will be used later to access the measurement bitstrings.\n", + "\n", + " ```python\n", + " # Define quantum circuit with 2 qubits\n", + " circuit = QuantumCircuit(2)\n", + " circuit.h(0)\n", + " circuit.cx(0, 1)\n", + " circuit.measure_all()\n", + " circuit.draw()\n", + " ```\n", + " ```text\n", + " ┌───┐ ░ ┌─┐\n", + " q_0: ┤ H ├──■───░─┤M├───\n", + " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", + " q_1: ─────┤ X ├─░──╫─┤M├\n", + " └───┘ ░ ║ └╥┘\n", + " meas: 2/══════════════╩══╩═\n", + " 0 1\n", + " ```\n", + "\n", + " ```python\n", + " # Run using V2 sampler\n", + " result = sampler_v2.run([circuit]).result()\n", + " # Access result data for PUB 0\n", + " data_pub = result[0].data\n", + " # Access bitstring for the classical register \"meas\"\n", + " bitstring = data_pub.meas.get_bitstring()\n", + " print(f\"The bitstring shape is: {bitstring.shape}\")\n", + " # Get counts for the classical register \"meas\"\n", + " counts = data_pub.meas.get_counts()\n", + " print(f\"The counts are: {counts}\")\n", + " ```\n", + " ```text\n", + " The bitstring shape is: (1024, 1)\n", + " The counts are: {'00': 523, '11': 501}\n", + " ```\n", + " \n", + "\n", + " \n", + "\n", + "\n", + "A quasi-probability distribution differs from a probability distribution in that negative values are also allowed.\n", + "However, the quasi-probabilities must sum up to 1 like probabilities.\n", + "Negative quasi-probabilities may appear when using error mitigation techniques.\n", + "\n", + " ```python\n", + " # Define quantum circuit with 2 qubits\n", + " circuit = QuantumCircuit(2)\n", + " circuit.h(0)\n", + " circuit.cx(0, 1)\n", + " circuit.measure_all()\n", + " circuit.draw()\n", + " ```\n", + "\n", + " ```python\n", + " # Run using V1 sampler\n", + " result = sampler_v1.run(circuit).result()\n", + " quasi_dist = result.quasi_dists[0]\n", + " print(f\"The quasi-probability distribution is: {quasi_dist}\")\n", + " ```\n", + " ```text\n", + " The quasi-probability distribution is: {0: 0.5, 3: 0.5}\n", + " ```\n", + "\n", + " If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method.\n", + "\n", + " ```python\n", + " print(quasi_dist.binary_probabilities())\n", + " ```\n", + "\n", + " ```python\n", + " {'00': 0.4999999999999999, '11': 0.4999999999999999}\n", + " ```\n", + "\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Change run options\n", + "\n", + "By default, the reference Sampler performs an exact statevector calculation based on the\n", + "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", + "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", + "\n", + "With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined.\n", + "The new interface accepts a `shots` argument that can be defined at the \"PUB level\".\n", + "\n", + "\n", + " \n", + "\n", + " ```python\n", + " # Sample two circuits at 128 shots each.\n", + " sampler_v2.run([circuit1, circuit2], shots=128)\n", + " # Sample two circuits at different amounts of shots. The \"None\"s are necessary\n", + " # as placeholders\n", + " # for the lack of parameter values in this example.\n", + " sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])\n", + " ```\n", + "\n", + " \n", + "\n", + " \n", + "\n", + " The V1 interface specifies shots in the following ways:\n", + "\n", + " - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.\n", + " - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.\n", + "\n", + " ```python\n", + " job = estimator.run(qc, observable, shots=2048, seed=123)\n", + " result = job.result()\n", + " print(result)\n", + " ```\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next steps\n", + "\n", + "\n", + " - For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer).\n", + " - To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial.\n", + " - Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference.\n", + " - Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference.\n", + " - Learn how to run on a physical system in the [Run](../run) section.\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
        ┌───┐      ░ ┌─┐   \n",
+       "   q_0: ┤ H ├──■───░─┤M├───\n",
+       "        └───┘┌─┴─┐ ░ └╥┘┌─┐\n",
+       "   q_1: ─────┤ X ├─░──╫─┤M├\n",
+       "             └───┘ ░  ║ └╥┘\n",
+       "meas: 2/══════════════╩══╩═\n",
+       "                      0  1 
" + ], + "text/plain": [ + " ┌───┐ ░ ┌─┐ \n", + " q_0: ┤ H ├──■───░─┤M├───\n", + " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", + " q_1: ─────┤ X ├─░──╫─┤M├\n", + " └───┘ ░ ║ └╥┘\n", + "meas: 2/══════════════╩══╩═\n", + " 0 1 " + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + " # Define quantum circuit with 2 qubits\n", + " circuit = QuantumCircuit(2)\n", + " circuit.h(0)\n", + " circuit.cx(0, 1)\n", + " circuit.measure_all()\n", + " circuit.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + }, + "title": "Exact simulation with Qiskit primitives" + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 6fe7a8ddfca..b8277570f10 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -405,6 +405,15 @@ Negative quasi-probabilities may appear when using error mitigation techniques. circuit.measure_all() circuit.draw() ``` + ```text + ┌───┐ ░ ┌─┐ + q_0: ┤ H ├──■───░─┤M├─── + └───┘┌─┴─┐ ░ └╥┘┌─┐ + q_1: ─────┤ X ├─░──╫─┤M├ + └───┘ ░ ║ └╥┘ + meas: 2/══════════════╩══╩═ + 0 1 + ``` ```python # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. From b2a9bbd09a64e1dfb34e14648c29c5b8e3509cc7 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Wed, 10 Apr 2024 16:16:34 -0400 Subject: [PATCH 39/60] rmv ipynb --- .../simulate-with-qiskit-primitives.ipynb | 616 ------------------ 1 file changed, 616 deletions(-) delete mode 100644 docs/verify/simulate-with-qiskit-primitives.ipynb diff --git a/docs/verify/simulate-with-qiskit-primitives.ipynb b/docs/verify/simulate-with-qiskit-primitives.ipynb deleted file mode 100644 index 94963515875..00000000000 --- a/docs/verify/simulate-with-qiskit-primitives.ipynb +++ /dev/null @@ -1,616 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Exact simulation with Qiskit primitives" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The reference primitives in Qiskit perform local statevector simulations. These simulations do not support\n", - "modeling device noise, but are useful for quickly prototyping algorithms before looking into more advanced simulation\n", - "techniques (using Qiskit Aer) or running on real devices (Qiskit Runtime primitives).\n", - "\n", - "The `Estimator` primitive can compute expectation values of circuits, and the `Sampler` primitive can sample\n", - "from output distributions of circuits.\n", - "\n", - "The following sections show how to use the reference primitives to run your workflow locally." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Use the reference `Estimator`\n", - "\n", - "There are two reference implementations of `Estimator` in `qiskit.primitives` that run on a local statevector\n", - "simulators: the [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) class and the\n", - "[`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class. The [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator)\n", - "implements the new Estimator V2 interface introduced in the Qiskit SDK 1.0, and offers additional input vectorization\n", - "features in comparison with the [`Estimator`](../api/qiskit/qiskit.primitives.Estimator) class, which implements the\n", - "legacy Estimator V1 interface. Both can take circuits, observables, and parameters as inputs and return the locally\n", - "computed expectation values.\n", - "\n", - "The following code prepares the inputs that will be used in the examples that follow. The expected input type for the\n", - "observables is [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Note that\n", - "the circuit in the example is parametrized, but you can also run the Estimator on non-parametrized circuits.\n", - "\n", - "\n", - " Any circuit passed to an Estimator must **not** include any **measurements**.\n", - "" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from qiskit import QuantumCircuit\n", - "from qiskit.circuit import Parameter\n", - "from qiskit.quantum_info import SparsePauliOp\n", - "\n", - "# circuit for which you want to obtain the expected value\n", - "qc = QuantumCircuit(2)\n", - "qc.ry(Parameter('theta'), 0)\n", - "qc.h(0)\n", - "qc.cx(0,1)\n", - "qc.draw(\"mpl\", style=\"iqp\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# observable(s) whose expected values you want to compute\n", - "observable = SparsePauliOp([\"II\", \"XX\", \"YY\", \"ZZ\"], coeffs=[1, 1, -1, 1])\n", - "\n", - "# value(s) for the circuit parameter(s)\n", - "import numpy as np\n", - "parameter_values = [[0], [np.pi/6], [np.pi/2]]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Initialize an Estimator\n", - "\n", - "To use the Estimator V2 implementation, follow the instructions to instantiate a\n", - "[`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator). If you want to maintain\n", - "your pre-existing workflow using an Estimator V1 implementation, you can also use the\n", - "[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class.\n", - "\n", - "\n", - " \n", - " Instantiate a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator).\n", - "\n", - "```python\n", - "from qiskit.primitives import StatevectorEstimator\n", - "estimator = StatevectorEstimator()\n", - "```\n", - " \n", - "\n", - " \n", - " Instantiate a [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator).\n", - "\n", - "```python\n", - "from qiskit.primitives import Estimator\n", - "estimator = Estimator()\n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run and get results\n", - "\n", - "This example only uses one circuit (of type [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) and one\n", - "observable.\n", - "\n", - "\n", - "\n", - " \n", - " Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run)\n", - " method, which returns an instance of a [PrimitiveJob](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the\n", - " job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object)\n", - " with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method.\n", - "\n", - "```python\n", - "job = estimator.run([(qc, observable, parameter_values)])\n", - "result = job.result()\n", - "print(f\" > Result class: {type(result)}\")\n", - "```\n", - "```text\n", - " > Result class: \n", - "```\n", - " \n", - " \n", - " Run the estimation by calling the [`Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method,\n", - " which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the\n", - " job (as an [`EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object)\n", - " with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", - "\n", - "```python\n", - "job = estimator.run([qc]*3, [observable]*3, parameter_values)\n", - "result = job.result()\n", - "print(f\" > Result class: {type(result)}\")\n", - "```\n", - "```text\n", - " > Result class: \n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Get the expected value from the result\n", - "\n", - "\n", - " \n", - "\n", - " The primitives V2 result outputs an array of [`PubResult`s](/api/qiskit/qiskit.primitives.PubResult#pubresult), where each item of the array is a `PubResult` object\n", - " that contains in its data the array of evaluations corresponding to every circuit-observable combination in the PUB.\n", - " To retrieve the expectation values and metadata for the first\n", - " (and in this case, only) circuit evaluation, we must access the evaluation [`data`](/api/qiskit/qiskit.primitives.PubResult#data) for PUB 0:\n", - "\n", - "```python\n", - "print(f\" > Expectation value: {result[0].data.evs}\")\n", - "print(f\" > Metadata: {result[0].metadata}\")\n", - "```\n", - "```text\n", - " > Expectation value: [4. 3.73205081 2. ]\n", - " > Metadata: {'precision': 0.0}\n", - "```\n", - " \n", - " \n", - "\n", - " The primitives V1 result stores an array of values that can be accessed through the attribute\n", - " [`EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values), where the`i`th\n", - " element is the expectation value corresponding to the `i`th circuit and `i`th observable.\n", - " To see the values for the first (and in this case, only) circuit evaluation, we must access the first item of the array.\n", - "\n", - "```python\n", - "print(f\" > Expectation value: {result.values[0]}\")\n", - "print(f\" > Metadata: {result.metadata}\")\n", - "```\n", - "\n", - "```text\n", - " > Expectation value: 3.999999999999999\n", - " > Metadata: [{}, {}, {}]\n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set Estimator run options\n", - "\n", - "By default, the reference Estimator performs an exact statevector calculation based on the\n", - "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", - "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", - "\n", - "With the introduction of the new V2 interface, the sampling overhead in the Estimator is now more concretely defined.\n", - "The new interface accepts a `precision` argument that expresses the error bars that the\n", - "primitive implementation should target for expectation values estimates,\n", - "instead of the number of `shots` used in the V1 interface.\n", - "\n", - "\n", - " \n", - "\n", - " The sampling overhead is now called `precision`, and is defined exclusively at the `.run()`\n", - " method level. This allows for a more finely-grained tuning of the option all the way to the PUB level.\n", - "\n", - " ```python\n", - " # Estimate expectation values for two PUBs, both with 0.05 precision.\n", - " estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)\n", - " ```\n", - "\n", - " \n", - "\n", - " \n", - "\n", - " The V1 interface specifies shots in the following ways:\n", - "\n", - " - Setting keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method.\n", - " - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options.\n", - "\n", - " ```python\n", - " job = estimator.run(qc, observable, shots=2048, seed=123)\n", - " result = job.result()\n", - " print(result)\n", - " ```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Use the reference `Sampler`\n", - "\n", - "Similar to the Estimator, there are two reference implementations of `Sampler` in `qiskit.primitives`:\n", - "the [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) class and the\n", - "[`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class. The [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler)\n", - "implements the new Estimator V2 interface introduced in Qiskit 1.0, and offers additional input vectorization\n", - "features in comparison with the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) class, which implements the\n", - "legacy Sampler V1 interface. Both can take circuits and parameters as inputs and return the results from sampling from\n", - "the output probability distributions, but they are expressed in different terms:\n", - "\n", - "- The new StatevectorSampler (V2) output can be expressed as an array of sampled values (bitstring) or \"counts\"\n", - " for each bitstring present in the output distribution.\n", - "- The Sampler (V1) output is always expressed as a quasi-probability distribution of output states.\n", - "\n", - "The following code prepares the inputs used in the examples that follow. Note that\n", - "these examples run a single parametrized circuit, but you can also run the Sampler\n", - "on non-parametrized circuits." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from qiskit import QuantumCircuit\n", - "\n", - "qc = QuantumCircuit(2)\n", - "qc.h(0)\n", - "qc.cx(0,1)\n", - "qc.measure_all()\n", - "qc.draw(\"mpl\", style=\"iqp\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Any quantum circuit passed to a Sampler **must** include measurements.\n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Initialize `Sampler`\n", - "\n", - "To use the Sampler V2 implementation, follow the instructions to instantiate a\n", - "[`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler). If you want to maintain\n", - "your pre-existing workflow using a Sampler V1 implementation, you can also use the\n", - "[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class.\n", - "\n", - "\n", - " \n", - " ```python\n", - "from qiskit.primitives import StatevectorSampler\n", - "\n", - "sampler = StatevectorSampler()\n", - "```\n", - " \n", - "\n", - " \n", - " ```python\n", - "from qiskit.primitives import Sampler\n", - "\n", - "sampler = Sampler()\n", - "```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run and get results\n", - "\n", - "\n", - " \n", - " ```python\n", - " # execute 1 circuit with 3 parameter sets using Sampler V2\n", - " job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])\n", - " counts = job.result()[0].data.meas.get_counts()\n", - " ```\n", - " V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result.\n", - " Therefore, you can run different circuits with various parameter/observable combinations,\n", - " which was not always possible in the V1 interface:\n", - "\n", - " ```python\n", - " # execute 2 circuits with 1 parameter set using Sampler V2\n", - " job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])\n", - " counts1 = job.result()\n", - " counts2 = job.result()\n", - " ```\n", - " \n", - "\n", - " \n", - " Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run)\n", - " method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1).\n", - " You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object)\n", - " with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method.\n", - "\n", - " ```python\n", - " job = sampler.run(qc)\n", - " result = job.result()\n", - " print(result)\n", - " ```\n", - "\n", - " ```python\n", - " SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}])\n", - " ```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Get the probability distribution or measurement outcome\n", - "\n", - "As mentioned above, the result retrieval step is different between V1 and V2 interfaces.\n", - "\n", - "The V1 sampler gives access to quasi-probability distributions.\n", - "\n", - "The V2 sampler returns measurement outcome samples in the form of **bitstrings** or\n", - "**counts**. The bitstrings show the measurement outcomes, preserving the shot\n", - "order in which they were measured. The V2 sampler result objects organize\n", - "data in terms of their input circuits' classical register names, for\n", - "compatibility with dynamic circuits.\n", - "\n", - "\n", - "\n", - " \n", - " The name of the classical register defaults to `\"meas\"`.\n", - " This name will be used later to access the measurement bitstrings.\n", - "\n", - " ```python\n", - " # Define quantum circuit with 2 qubits\n", - " circuit = QuantumCircuit(2)\n", - " circuit.h(0)\n", - " circuit.cx(0, 1)\n", - " circuit.measure_all()\n", - " circuit.draw()\n", - " ```\n", - " ```text\n", - " ┌───┐ ░ ┌─┐\n", - " q_0: ┤ H ├──■───░─┤M├───\n", - " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", - " q_1: ─────┤ X ├─░──╫─┤M├\n", - " └───┘ ░ ║ └╥┘\n", - " meas: 2/══════════════╩══╩═\n", - " 0 1\n", - " ```\n", - "\n", - " ```python\n", - " # Run using V2 sampler\n", - " result = sampler_v2.run([circuit]).result()\n", - " # Access result data for PUB 0\n", - " data_pub = result[0].data\n", - " # Access bitstring for the classical register \"meas\"\n", - " bitstring = data_pub.meas.get_bitstring()\n", - " print(f\"The bitstring shape is: {bitstring.shape}\")\n", - " # Get counts for the classical register \"meas\"\n", - " counts = data_pub.meas.get_counts()\n", - " print(f\"The counts are: {counts}\")\n", - " ```\n", - " ```text\n", - " The bitstring shape is: (1024, 1)\n", - " The counts are: {'00': 523, '11': 501}\n", - " ```\n", - " \n", - "\n", - " \n", - "\n", - "\n", - "A quasi-probability distribution differs from a probability distribution in that negative values are also allowed.\n", - "However, the quasi-probabilities must sum up to 1 like probabilities.\n", - "Negative quasi-probabilities may appear when using error mitigation techniques.\n", - "\n", - " ```python\n", - " # Define quantum circuit with 2 qubits\n", - " circuit = QuantumCircuit(2)\n", - " circuit.h(0)\n", - " circuit.cx(0, 1)\n", - " circuit.measure_all()\n", - " circuit.draw()\n", - " ```\n", - "\n", - " ```python\n", - " # Run using V1 sampler\n", - " result = sampler_v1.run(circuit).result()\n", - " quasi_dist = result.quasi_dists[0]\n", - " print(f\"The quasi-probability distribution is: {quasi_dist}\")\n", - " ```\n", - " ```text\n", - " The quasi-probability distribution is: {0: 0.5, 3: 0.5}\n", - " ```\n", - "\n", - " If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the [`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method.\n", - "\n", - " ```python\n", - " print(quasi_dist.binary_probabilities())\n", - " ```\n", - "\n", - " ```python\n", - " {'00': 0.4999999999999999, '11': 0.4999999999999999}\n", - " ```\n", - "\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Change run options\n", - "\n", - "By default, the reference Sampler performs an exact statevector calculation based on the\n", - "[`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class.\n", - "However, this can be modified to introduce the effect of the sampling overhead (also known as \"shot noise\").\n", - "\n", - "With the introduction of the new V2 interface, the sampling overhead in the Sampler is now more precisely defined.\n", - "The new interface accepts a `shots` argument that can be defined at the \"PUB level\".\n", - "\n", - "\n", - " \n", - "\n", - " ```python\n", - " # Sample two circuits at 128 shots each.\n", - " sampler_v2.run([circuit1, circuit2], shots=128)\n", - " # Sample two circuits at different amounts of shots. The \"None\"s are necessary\n", - " # as placeholders\n", - " # for the lack of parameter values in this example.\n", - " sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])\n", - " ```\n", - "\n", - " \n", - "\n", - " \n", - "\n", - " The V1 interface specifies shots in the following ways:\n", - "\n", - " - Setting keyword arguments in the [`Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method.\n", - " - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options.\n", - "\n", - " ```python\n", - " job = estimator.run(qc, observable, shots=2048, seed=123)\n", - " result = job.result()\n", - " print(result)\n", - " ```\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Next steps\n", - "\n", - "\n", - " - For higher-performance simulation that can handle larger circuits, or to incorporate noise models into your simulation, see [Exact and noisy simulation with Qiskit Aer primitives](simulate-with-qiskit-aer).\n", - " - To learn how to use Quantum Composer for simulation, try the [Explore gates and circuits with the Quantum Composer](https://learning.quantum.ibm.com/tutorial/explore-gates-and-circuits-with-the-quantum-composer) tutorial.\n", - " - Read the [Qiskit Estimator API](/api/qiskit/qiskit.primitives.Estimator) reference.\n", - " - Read the [Qiskit Sampler API](/api/qiskit/qiskit.primitives.Sampler) reference.\n", - " - Learn how to run on a physical system in the [Run](../run) section.\n", - "" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
        ┌───┐      ░ ┌─┐   \n",
-       "   q_0: ┤ H ├──■───░─┤M├───\n",
-       "        └───┘┌─┴─┐ ░ └╥┘┌─┐\n",
-       "   q_1: ─────┤ X ├─░──╫─┤M├\n",
-       "             └───┘ ░  ║ └╥┘\n",
-       "meas: 2/══════════════╩══╩═\n",
-       "                      0  1 
" - ], - "text/plain": [ - " ┌───┐ ░ ┌─┐ \n", - " q_0: ┤ H ├──■───░─┤M├───\n", - " └───┘┌─┴─┐ ░ └╥┘┌─┐\n", - " q_1: ─────┤ X ├─░──╫─┤M├\n", - " └───┘ ░ ║ └╥┘\n", - "meas: 2/══════════════╩══╩═\n", - " 0 1 " - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - " # Define quantum circuit with 2 qubits\n", - " circuit = QuantumCircuit(2)\n", - " circuit.h(0)\n", - " circuit.cx(0, 1)\n", - " circuit.measure_all()\n", - " circuit.draw()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "description": "How to perform exact simulation of quantum circuits using primitives in Qiskit.", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.0" - }, - "title": "Exact simulation with Qiskit primitives" - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 9d300788518bdb0dab72255137ebb93c550da425 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 09:53:11 -0400 Subject: [PATCH 40/60] Update docs/verify/simulate-with-qiskit-primitives.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --- docs/verify/simulate-with-qiskit-primitives.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index b8277570f10..5a9518cab52 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -45,6 +45,9 @@ qc.draw("mpl", style="iqp") ![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png "Initial QuantumCircuit") ```python +from qiskit.quantum_info import SparsePauliOp +import numpy as np + # observable(s) whose expected values you want to compute observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) From 5317503f64a7484c5f44a6240eaa03988a0b5e81 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 09:55:44 -0400 Subject: [PATCH 41/60] Update docs/verify/simulate-with-qiskit-primitives.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 5a9518cab52..99bd23fd5c5 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -91,7 +91,7 @@ observable. Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) - method, which returns an instance of a [PrimitiveJob](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the + method, which returns an instance of a [`PrimitiveJob`](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method. From 625a60e7624209833798a27598b22c4ae89525f2 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 09:59:23 -0400 Subject: [PATCH 42/60] Update docs/verify/simulate-with-qiskit-primitives.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --- docs/verify/simulate-with-qiskit-primitives.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 99bd23fd5c5..a8680e1e984 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -52,7 +52,6 @@ import numpy as np observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) # value(s) for the circuit parameter(s) -import numpy as np parameter_values = [[0], [np.pi/6], [np.pi/2]] ``` ### Initialize Estimator From cb6c8c70fcbec74cb85da0c47c2ed45deee25724 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 10:44:26 -0400 Subject: [PATCH 43/60] code review --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index b8277570f10..a95f70e747f 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -33,7 +33,6 @@ the circuit in the example is parametrized, but you can also run the Estimator o ```python from qiskit import QuantumCircuit from qiskit.circuit import Parameter -from qiskit.quantum_info import SparsePauliOp # circuit for which you want to obtain the expected value qc = QuantumCircuit(2) @@ -46,6 +45,7 @@ qc.draw("mpl", style="iqp") ```python # observable(s) whose expected values you want to compute +from qiskit.quantum_info import SparsePauliOp observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) # value(s) for the circuit parameter(s) From 596a5d854164e7ff566f095234a01bbafb41379c Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 10:48:36 -0400 Subject: [PATCH 44/60] add ISA message --- docs/verify/simulate-with-qiskit-primitives.mdx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 7721c036bcb..f3f7869fea7 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -54,6 +54,20 @@ observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) # value(s) for the circuit parameter(s) parameter_values = [[0], [np.pi/6], [np.pi/2]] ``` + + + The Qiskit Runtime primitives workflow requires circuits and observables to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables). The reference primitives still accept abstract instructions, as they rely on local statevector simulations, but transpiling the circuit might still be beneficial in terms of circuit optimization. + + ```python + # Generate a pass manager without providing a backend + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(optimization_level=1) + isa_circuit = pm.run(qc) + isa_observable = observable.apply_layout(isa_circuit.layout) + ``` + + ### Initialize Estimator To use the Estimator V2 implementation, follow the instructions to instantiate a From bd05d077a5deb10db576114e98ee58e330191cb1 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 10:50:32 -0400 Subject: [PATCH 45/60] Update simulate-with-qiskit-primitives.mdx --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f3f7869fea7..89396f900f2 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -106,7 +106,7 @@ observable. Run the estimation by calling the [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) method, which returns an instance of a [`PrimitiveJob`](/api/qiskit/qiskit.primitives.PrimitiveJob) object. You can get the results from the job (as a [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) object) - with the [`qiskit.primitives.PrimitiveResult.primitiveresult`](../api/qiskit/qiskit.primitives.PrimitiveResult#primitiveresult) method. + with the [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.primitives.PrimitiveJob#result) method. ```python # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. From 2bcc8afe9ae8e915bf6566257064698d55775cda Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 10:56:29 -0400 Subject: [PATCH 46/60] Update simulate-with-qiskit-primitives.mdx --- docs/verify/simulate-with-qiskit-primitives.mdx | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 89396f900f2..39e74ff6ebc 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -109,13 +109,7 @@ observable. with the [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.primitives.PrimitiveJob#result) method. ```python -# Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. -from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - -pm = generate_preset_pass_manager(backend=backend, optimization_level=1) -isa_circuit = pm.run(qc) - -job = estimator.run([(isa_circuit, observable, parameter_values)]) +job = estimator.run([(isa_circuit, isa_observable, parameter_values)]) result = job.result() print(f" > Result class: {type(result)}") ``` @@ -130,13 +124,10 @@ print(f" > Result class: {type(result)}") with the [`JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python -# Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. -from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) isa_circuit = pm.run(qc) -job = estimator.run([isa_circuit]*3, [observable]*3, parameter_values) +job = estimator.run([isa_circuit]*3, [isa_observable]*3, parameter_values) result = job.result() print(f" > Result class: {type(result)}") ``` From 7440557c4a501893bdd6a61f65453f87e079cede Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 11:10:39 -0400 Subject: [PATCH 47/60] rest of code review --- .../simulate-with-qiskit-primitives.mdx | 99 ++++++++----------- 1 file changed, 42 insertions(+), 57 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 39e74ff6ebc..2b6bc9f61f4 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -193,15 +193,8 @@ instead of the number of `shots` used in the V1 interface. method level. This allows for a more finely-grained tuning of the option all the way to the PUB level. ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) - isa_circuit1 = pm.run(circuit1) - isa_circuit2 = pm.run(circuit2) - # Estimate expectation values for two PUBs, both with 0.05 precision. - estimator.run([(isa_circuit1, obs_array1), (isa_circuit2, obs_array_2)], precision=0.05) + estimator.run([(isa_circuit1, isa_obs_array1), (isa_circuit2, isa_obs_array_2)], precision=0.05) ``` @@ -214,13 +207,7 @@ instead of the number of `shots` used in the V1 interface. - Modifying the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) - isa_circuit = pm.run(qc) - - job = estimator.run(isa_circuit, observable, shots=2048, seed=123) + job = estimator.run(isa_circuit, isa_observable, shots=2048, seed=123) result = job.result() print(result) ``` @@ -262,6 +249,19 @@ qc.draw("mpl", style="iqp") Any quantum circuit passed to a Sampler **must** include measurements. + + The Qiskit Runtime primitives workflow requires circuits and observables to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables). The reference primitives still accept abstract instructions, as they rely on local statevector simulations, but transpiling the circuit might still be beneficial in terms of circuit optimization. + + ```python + # Generate a pass manager without providing a backend + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + + pm = generate_preset_pass_manager(optimization_level=1) + isa_circuit = pm.run(qc) + isa_observable = observable.apply_layout(isa_circuit.layout) + ``` + + ### Initialize `Sampler` To use the Sampler V2 implementation, follow the instructions to instantiate a @@ -291,32 +291,36 @@ sampler = Sampler() ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) - isa_circuit = pm.run(circuit) - - # execute 1 circuit with 3 parameter sets using Sampler V2 + # execute 1 circuit with 3 parameter sets using Sampler V2 job = sampler.run([(isa_circuit, [vals1, vals2, vals3])]) - counts = job.result()[0].data.meas.get_counts() + pub_result = job.result()[0] + print(f" > Result class: {type(pub_result)}") ``` + ```text + > Result class: + ``` + V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result. - Therefore, you can run different circuits with various parameter/observable combinations, - which was not always possible in the V1 interface: + Therefore, you can run different circuits with various parameter/observable combinations, and retrieve the PUB results: ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + + # create two circuits + circuit1 = qc.copy() + circuit2 = qc.copy() + + # transpile circuits + pm = generate_preset_pass_manager(optimization_level=1) isa_circuit1 = pm.run(circuit1) isa_circuit2 = pm.run(circuit2) - # execute 2 circuits with 1 parameter set using Sampler V2 job = sampler.run([(isa_circuit1, vals1), (isa_circuit2, vals1)]) - counts1 = job.result() - counts2 = job.result() + pub_result_1 = job.result()[0] + pub_result_2 = job.result()[1] + ``` + ```text + RESULT HERE XXX ``` @@ -327,18 +331,12 @@ sampler = Sampler() with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) - isa_circuit = pm.run(circuit) - job = sampler.run(isa_circuit) result = job.result() print(result) ``` - ```python + ```text SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) ``` @@ -380,6 +378,9 @@ compatibility with dynamic circuits. ``` ```python + # Transpile circuit + pm = generate_preset_pass_manager(optimization_level=1) + isa_circuit = pm.run(circuit) # Run using V2 sampler result = sampler_v2.run([circuit]).result() # Access result data for PUB 0 @@ -423,12 +424,9 @@ Negative quasi-probabilities may appear when using error mitigation techniques. ``` ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + # Transpile circuit + pm = generate_preset_pass_manager(optimization_level=1) isa_circuit = pm.run(circuit) - # Run using V1 sampler result = sampler_v1.run(isa_circuit).result() quasi_dist = result.quasi_dists[0] @@ -464,13 +462,6 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) - isa_circuit1 = pm.run(circuit1) - isa_circuit2 = pm.run(circuit2) - # Sample two circuits at 128 shots each. sampler.run([isa_circuit1, isa_circuit2], shots=128) # Sample two circuits at different amounts of shots. The "None"s are necessary @@ -489,13 +480,7 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev - Modifying the [`Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. ```python - # Circuits and parameters must obey the Instruction Set Architecture (ISA) of a particular backend. - from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - - pm = generate_preset_pass_manager(backend=backend, optimization_level=1) - isa_circuit = pm.run(circuit) - - job = sampler.run(isa_circuit, observable, shots=2048, seed=123) + job = sampler.run(isa_circuit, shots=2048, seed=123) result = job.result() print(result) ``` From e331fa0c1c4cabfc0afdeac21644b2c6deebb28d Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 11:43:35 -0400 Subject: [PATCH 48/60] add result --- .gitignore | 1 + docs/verify/simulate-with-qiskit-primitives.mdx | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index c6c11e01204..2ec51a36c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ tsconfig.tsbuildinfo /.sphinx-artifacts/ poetry.lock pyproject.toml +docs/verify/simulate-with-qiskit-primitives.ipynb diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 2b6bc9f61f4..8d2eb8724bf 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -484,6 +484,9 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev result = job.result() print(result) ``` + ```text + SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) + ``` From 6e9bd9a0e99596f185d30fcaee880922f3e58f34 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 11:54:44 -0400 Subject: [PATCH 49/60] testing out print statement --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 8d2eb8724bf..f6dde3a0881 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -318,9 +318,7 @@ sampler = Sampler() job = sampler.run([(isa_circuit1, vals1), (isa_circuit2, vals1)]) pub_result_1 = job.result()[0] pub_result_2 = job.result()[1] - ``` - ```text - RESULT HERE XXX + print(f" > Result class: {type(pub_result)}") ``` From 3a90933fe0b11d2674494e9eeccba8d2d8ee6d3d Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 12:04:12 -0400 Subject: [PATCH 50/60] Update .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2ec51a36c5d..c6c11e01204 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,3 @@ tsconfig.tsbuildinfo /.sphinx-artifacts/ poetry.lock pyproject.toml -docs/verify/simulate-with-qiskit-primitives.ipynb From 5d0ceb7c5c9c6e0da294f0e4df3e861a7ad14e40 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 12:44:57 -0400 Subject: [PATCH 51/60] Update docs/verify/simulate-with-qiskit-primitives.mdx --- docs/verify/simulate-with-qiskit-primitives.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f6dde3a0881..7633d9491c9 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -209,7 +209,6 @@ instead of the number of `shots` used in the V1 interface. ```python job = estimator.run(isa_circuit, isa_observable, shots=2048, seed=123) result = job.result() - print(result) ``` From 20a386919acd8c33b54649adb79c120d347a141f Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 12:56:14 -0400 Subject: [PATCH 52/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 7633d9491c9..600e1086a79 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -213,7 +213,7 @@ instead of the number of `shots` used in the V1 interface. -See more examples on the [Primitives examples](/run/primitives-examples#estimator-examples) page. +For a full example, see the [Primitives examples](/run/primitives-examples#estimator-examples) page. ## Use the reference `Sampler` From d7c2fa6c4eaf3963b4382f59aa0e387eb5085704 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 12:58:11 -0400 Subject: [PATCH 53/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 600e1086a79..2b943ea1749 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -487,7 +487,7 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev -See more examples on the [Primitives examples](/run/primitives-examples#sampler-examples) page. +For a full example, see the [Primitives examples](/run/primitives-examples#sampler-examples) page. ## Next steps From c9b97852f19b6108378488ef27f169879bf13bcd Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 12:59:45 -0400 Subject: [PATCH 54/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 2b943ea1749..248c9b91c37 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -191,6 +191,8 @@ instead of the number of `shots` used in the V1 interface. The sampling overhead is now called `precision`, and is defined exclusively at the `.run()` method level. This allows for a more finely-grained tuning of the option all the way to the PUB level. + + This example assumes you have defined two circuits, each with its own array of observables. ```python # Estimate expectation values for two PUBs, both with 0.05 precision. From 4116f77df98420dc78d7624de333e2b8423e3226 Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 13:07:39 -0400 Subject: [PATCH 55/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 248c9b91c37..6c1093a9c80 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -292,13 +292,13 @@ sampler = Sampler() ```python - # execute 1 circuit with 3 parameter sets using Sampler V2 - job = sampler.run([(isa_circuit, [vals1, vals2, vals3])]) + # execute 1 circuit with Sampler V2 + job = sampler.run([isa_circuit]) pub_result = job.result()[0] print(f" > Result class: {type(pub_result)}") ``` ```text - > Result class: + > Result class: ``` V2 primitives accept multiple PUBs as inputs, and each PUB gets its own result. From 1c1281a0f35cad95e372f2d9899336d60142fbba Mon Sep 17 00:00:00 2001 From: abbycross Date: Thu, 11 Apr 2024 13:12:50 -0400 Subject: [PATCH 56/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 6c1093a9c80..43c47528681 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -315,8 +315,8 @@ sampler = Sampler() pm = generate_preset_pass_manager(optimization_level=1) isa_circuit1 = pm.run(circuit1) isa_circuit2 = pm.run(circuit2) - # execute 2 circuits with 1 parameter set using Sampler V2 - job = sampler.run([(isa_circuit1, vals1), (isa_circuit2, vals1)]) + # execute 2 circuits using Sampler V2 + job = sampler.run([(isa_circuit1), (isa_circuit2)]) pub_result_1 = job.result()[0] pub_result_2 = job.result()[1] print(f" > Result class: {type(pub_result)}") From 38e5c316e8721fc2a4f7076fb78f6683f980d2ac Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 13:15:55 -0400 Subject: [PATCH 57/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 43c47528681..36b1635dfdf 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -321,10 +321,13 @@ sampler = Sampler() pub_result_2 = job.result()[1] print(f" > Result class: {type(pub_result)}") ``` + ```text + > Result class: + ``` - Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) + Run Sampler by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. @@ -381,7 +384,7 @@ compatibility with dynamic circuits. pm = generate_preset_pass_manager(optimization_level=1) isa_circuit = pm.run(circuit) # Run using V2 sampler - result = sampler_v2.run([circuit]).result() + result = sampler.run([circuit]).result() # Access result data for PUB 0 data_pub = result[0].data # Access bitstring for the classical register "meas" From 0b51021912d0f3f31ecb8d2c9e7b49ffceb71062 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 13:21:49 -0400 Subject: [PATCH 58/60] Becky review --- docs/verify/simulate-with-qiskit-primitives.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 36b1635dfdf..c8a18dfb528 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -388,15 +388,15 @@ compatibility with dynamic circuits. # Access result data for PUB 0 data_pub = result[0].data # Access bitstring for the classical register "meas" - bitstring = data_pub.meas.get_bitstring() - print(f"The bitstring shape is: {bitstring.shape}") + bitstrings = data_pub.meas.get_bitstrings() + print(f"The number of bitstrings is: {len(bitstrings)}") # Get counts for the classical register "meas" counts = data_pub.meas.get_counts() print(f"The counts are: {counts}") ``` ```text - The bitstring shape is: (1024, 1) - The counts are: {'00': 523, '11': 501} + The number of bitstrings is: 1024 + The counts are: {'11': 503, '00': 521} ``` From 5c77ba3bf5d67284e0c0873c7c2484c66acff5dd Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 13:23:48 -0400 Subject: [PATCH 59/60] Becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index c8a18dfb528..9040058deae 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -463,6 +463,8 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev + This example assumes you have defined two circuits. + ```python # Sample two circuits at 128 shots each. sampler.run([isa_circuit1, isa_circuit2], shots=128) From 9ae023847a0e51a3e4090cb65bda8e668c271388 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Thu, 11 Apr 2024 14:43:16 -0400 Subject: [PATCH 60/60] becky's review --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 9040058deae..d18bf52ecdf 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -251,7 +251,7 @@ Any quantum circuit passed to a Sampler **must** include measurements. - The Qiskit Runtime primitives workflow requires circuits and observables to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits and observables). The reference primitives still accept abstract instructions, as they rely on local statevector simulations, but transpiling the circuit might still be beneficial in terms of circuit optimization. + The Qiskit Runtime primitives workflow requires circuits to be transformed to only use instructions supported by the system (referred to as *instruction set architecture (ISA)* circuits). The reference primitives still accept abstract instructions, as they rely on local statevector simulations, but transpiling the circuit might still be beneficial in terms of circuit optimization. ```python # Generate a pass manager without providing a backend @@ -464,7 +464,7 @@ The new interface accepts a `shots` argument that can be defined at the "PUB lev This example assumes you have defined two circuits. - + ```python # Sample two circuits at 128 shots each. sampler.run([isa_circuit1, isa_circuit2], shots=128)