From 6cf2da6afcfa152cbe00db897373df2ebf140ba7 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Mon, 16 Oct 2023 12:06:06 -0400 Subject: [PATCH 01/14] combine how-tos --- docs/verify/simulate-with-primitives.mdx | 595 +++++++++++++++++++++++ 1 file changed, 595 insertions(+) create mode 100644 docs/verify/simulate-with-primitives.mdx diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx new file mode 100644 index 00000000000..37ad071c270 --- /dev/null +++ b/docs/verify/simulate-with-primitives.mdx @@ -0,0 +1,595 @@ +--- +title: Simulate using Qiskit reference primitives +description: How to compute an expectation value with the Estimator primitive, and how to compute circuit output probabilities with the Sampler primitive +--- + +# Simulate using Qiskit reference primitives + +## Compute an expectation value with `Estimator` primitive + +This guide shows how to get the expected value of an observable for a given quantum circuit with the {class}`~qiskit.primitives.Estimator` primitive. + +:::{note} +While this guide uses Qiskit’s reference implementation, the `Estimator` primitive can be run with any provider using {class}`~qiskit.primitives.BackendEstimator` . + +``` +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 [this page](http://qiskit.org/providers/#primitives) for more details). +::: + +## 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 {mod}`qiskit.quantum_info`. +Among them it is preferable to use {class}`~qiskit.quantum_info.SparsePauliOp`. + +```{eval-rst} +.. testcode:: + + from qiskit.quantum_info import SparsePauliOp + + observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) +``` + +## Initialize quantum circuit + +Then you need to create the {class}`~qiskit.circuit.QuantumCircuit`s for which you want to obtain the expected value. + +```{eval-rst} +.. plot:: + :include-source: + + from qiskit import QuantumCircuit + + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0,1) + qc.draw("mpl") +``` + +```{eval-rst} +.. testsetup:: + + # This code is repeated (but hidden) because we will need to use the variables with the extension sphinx.ext.doctest (testsetup/testcode/testoutput directives) + # and we can't reuse the variables from the plot directive above because they are incompatible. + # The plot directive is used to draw the circuit with matplotlib and the code is shown because of the include-source flag. + + from qiskit import QuantumCircuit + + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0,1) +``` + +:::{note} +The {class}`~qiskit.circuit.QuantumCircuit` you pass to {class}`~qiskit.primitives.Estimator` must not include any measurements. +::: + +## Initialize the `Estimator` + +Then, you need to instantiate an {class}`~qiskit.primitives.Estimator`. + +```{eval-rst} +.. testcode:: + + 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 {meth}`~qiskit.primitives.Estimator.run` method, +which returns an instance of {class}`~.PrimitiveJob` (subclass of {class}`~qiskit.providers.JobV1`). You can get the results from the job (as a {class}`~qiskit.primitives.EstimatorResult` object) +with the {meth}`~qiskit.providers.JobV1.result` method. + +```{eval-rst} +.. testcode:: + + job = estimator.run(qc, observable) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + EstimatorResult(values=array([4.]), metadata=[{}]) +``` + +While this example only uses one {class}`~qiskit.circuit.QuantumCircuit` and one observable, if you want to get expectation values for multiple circuits and observables you can +pass a `list` of {class}`~qiskit.circuit.QuantumCircuit`s and a list of `BaseOperator`s to the {meth}`~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 {attr}`~qiskit.primitives.EstimatorResult.values`. + +{attr}`~qiskit.primitives.EstimatorResult.values` returns a {class}`numpy.ndarray` +whose `i`-th element is the expectation value corresponding to the `i`-th circuit and `i`-th observable. + +```{eval-rst} +.. testcode:: + + exp_value = result.values[0] + print(exp_value) +``` + +```{eval-rst} +.. testoutput:: + + 3.999999999999999 +``` + +## Parameterized circuit with `Estimator` + +The {class}`~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. + +```{eval-rst} +.. testcode:: + + from qiskit.circuit import Parameter + + theta = Parameter('θ') + param_qc = QuantumCircuit(2) + param_qc.ry(theta, 0) + param_qc.cx(0,1) + print(param_qc.draw()) +``` + +```{eval-rst} +.. testoutput:: + + ┌───────┐ + q_0: ┤ Ry(θ) ├──■── + └───────┘┌─┴─┐ + q_1: ─────────┤ X ├ + └───┘ +``` + +The main difference with the previous case is that now you need to specify the sets of parameter values +for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. +The `i`-th element of the outer\`\`list\`\` is the set of parameter values +that corresponds to the `i`-th circuit and observable. + +```{eval-rst} +.. testcode:: + + import numpy as np + + parameter_values = [[0], [np.pi/6], [np.pi/2]] + + job = estimator.run([param_qc]*3, [observable]*3, parameter_values=parameter_values) + values = job.result().values + + for i in range(3): + print(f"Parameter: {parameter_values[i][0]:.5f}\t Expectation value: {values[i]}") +``` + +```{eval-rst} +.. testoutput:: + + 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 amount of shots. + +By default, the reference {class}`~qiskit.primitives.Estimator` class performs an exact statevector +calculation based on the {class}`~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 {class}`~qiskit.primitives.Estimator`: + +- Set keyword arguments in the {meth}`~qiskit.primitives.Estimator.run` method. +- Modify {class}`~qiskit.primitives.Estimator` options. + +### Set keyword arguments for {meth}`~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 {meth}`~qiskit.primitives.Estimator.run` method. You can do this by +passing them as keyword arguments. + +```{eval-rst} +.. testcode:: + + job = estimator.run(qc, observable, shots=2048, seed=123) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) +``` + +```{eval-rst} +.. testcode:: + + print(result.values[0]) +``` + +```{eval-rst} +.. testoutput:: + + 3.999999998697238 +``` + +### Modify {class}`~qiskit.primitives.Estimator` options + +If you want to keep some configuration values for several runs, it can be better to +change the {class}`~qiskit.primitives.Estimator` options. That way you can use the same +{class}`~qiskit.primitives.Estimator` object as many times as you wish without having to +rewrite the configuration values every time you use {meth}`~qiskit.primitives.Estimator.run`. + +#### Modify existing {class}`~qiskit.primitives.Estimator` + +If you prefer to change the options of an already-defined {class}`~qiskit.primitives.Estimator`, you can use +{meth}`~qiskit.primitives.Estimator.set_options` and introduce the new options as keyword arguments. + +```{eval-rst} +.. testcode:: + + estimator.set_options(shots=2048, seed=123) + + job = estimator.run(qc, observable) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) +``` + +```{eval-rst} +.. testcode:: + + print(result.values[0]) +``` + +```{eval-rst} +.. testoutput:: + + 3.999999998697238 + +``` + +#### Define a new {class}`~qiskit.primitives.Estimator` with the options + +If you prefer to define a new {class}`~qiskit.primitives.Estimator` with new options, you need to +define a `dict` like this one: + +```{eval-rst} +.. testcode:: + + options = {"shots": 2048, "seed": 123} +``` + +And then you can introduce it into your new {class}`~qiskit.primitives.Estimator` with the +`options` argument. + +```{eval-rst} +.. testcode:: + + estimator = Estimator(options=options) + + job = estimator.run(qc, observable) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) +``` + +```{eval-rst} +.. testcode:: + + print(result.values[0]) +``` + +```{eval-rst} +.. testoutput:: + + 3.999999998697238 +``` + +## Compute circuit output probabilities with `Sampler` primitive + +This guide shows how to get the probability distribution of a quantum circuit with the {class}`~qiskit.primitives.Sampler` primitive. + +:::{note} +While this guide uses Qiskit’s reference implementation, the `Sampler` primitive can be run with any provider using {class}`~qiskit.primitives.BackendSampler`. + +``` +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 [this page](http://qiskit.org/providers/#primitives) for more details). +::: + +## Initialize quantum circuits + +The first step is to create the {class}`~qiskit.circuit.QuantumCircuit`s from which you want to obtain the probability distribution. + +```{eval-rst} +.. plot:: + :include-source: + + from qiskit import QuantumCircuit + + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0,1) + qc.measure_all() + qc.draw("mpl") +``` + +```{eval-rst} +.. testsetup:: + + # This code is repeated (but hidden) because we will need to use the variables with the extension sphinx.ext.doctest (testsetup/testcode/testoutput directives) + # and we can't reuse the variables from the plot directive above because they are incompatible. + # The plot directive is used to draw the circuit with matplotlib and the code is shown because of the include-source flag. + + from qiskit import QuantumCircuit + + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0,1) + qc.measure_all() +``` + +:::{note} +The {class}`~qiskit.circuit.QuantumCircuit` you pass to {class}`~qiskit.primitives.Sampler` has to include measurements. +::: + +## Initialize the `Sampler` + +Then, you need to create a {class}`~qiskit.primitives.Sampler` instance. + +```{eval-rst} +.. testcode:: + + from qiskit.primitives import Sampler + + sampler = Sampler() +``` + +## Run and get results + +Now that you have defined your `sampler`, you can run it by calling the {meth}`~qiskit.primitives.Sampler.run` method, +which returns an instance of {class}`~.PrimitiveJob` (subclass of {class}`~qiskit.providers.JobV1`). You can get the results from the job (as a {class}`~qiskit.primitives.SamplerResult` object) +with the {meth}`~qiskit.providers.JobV1.result` method. + +```{eval-rst} +.. testcode:: + + job = sampler.run(qc) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) +``` + +While this example only uses one {class}`~qiskit.circuit.QuantumCircuit`, if you want to sample multiple circuits you can +pass a `list` of {class}`~qiskit.circuit.QuantumCircuit` instances to the {meth}`~qiskit.primitives.Sampler.run` method. + +### Get the probability distribution + +From these results you can extract the quasi-probability distributions with the attribute {attr}`~qiskit.primitives.SamplerResult.quasi_dists`. + +Even though there is only one circuit in this example, {attr}`~qiskit.primitives.SamplerResult.quasi_dists` returns a list of {class}`~qiskit.result.QuasiDistribution`s. +`result.quasi_dists[i]` is the quasi-probability distribution of the `i`-th circuit. + +:::{note} +A quasi-probability distribution differs from a probability distribution in that negative values are also allowed. +However the quasi-probabilities must sum up to 1 like probabilities. +Negative quasi-probabilities may appear when using error mitigation techniques. +::: + +```{eval-rst} +.. testcode:: + + quasi_dist = result.quasi_dists[0] + print(quasi_dist) +``` + +```{eval-rst} +.. testoutput:: + + {0: 0.4999999999999999, 3: 0.4999999999999999} +``` + +#### Probability distribution with binary outputs + +If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the +{meth}`~qiskit.result.QuasiDistribution.binary_probabilities` method. + +```{eval-rst} +.. testcode:: + + print(quasi_dist.binary_probabilities()) +``` + +```{eval-rst} +.. testoutput:: + + {'00': 0.4999999999999999, '11': 0.4999999999999999} +``` + +## Parameterized circuit with `Sampler` + +The {class}`~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. + +```{eval-rst} +.. testcode:: + + from qiskit.circuit import Parameter + + theta = Parameter('θ') + param_qc = QuantumCircuit(2) + param_qc.ry(theta, 0) + param_qc.cx(0,1) + param_qc.measure_all() + print(param_qc.draw()) +``` + +```{eval-rst} +.. testoutput:: + + ┌───────┐ ░ ┌─┐ + q_0: ┤ Ry(θ) ├──■───░─┤M├─── + └───────┘┌─┴─┐ ░ └╥┘┌─┐ + q_1: ─────────┤ X ├─░──╫─┤M├ + └───┘ ░ ║ └╥┘ + meas: 2/══════════════════╩══╩═ + 0 1 +``` + +The main difference from the previous case is that now you need to specify the sets of parameter values +for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. +The `i`-th element of the outer `list` is the set of parameter values +that corresponds to the `i`-th circuit. + +```{eval-rst} +.. testcode:: + + import numpy as np + + parameter_values = [[0], [np.pi/6], [np.pi/2]] + + job = sampler.run([param_qc]*3, parameter_values=parameter_values) + dists = job.result().quasi_dists + + for i in range(3): + print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}") +``` + +```{eval-rst} +.. testoutput:: + + Parameter: 0.00000 Probabilities: {0: 1.0} + Parameter: 0.52360 Probabilities: {0: 0.9330127018922194, 3: 0.0669872981077807} + Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.4999999999999999} +``` + +## Change run options + +Your workflow might require tuning primitive run options, such as the amount of shots. + +By default, the reference {class}`~qiskit.primitives.Sampler` class performs an exact statevector +calculation based on the {class}`~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 {class}`~qiskit.primitives.Sampler`: + +- Set keyword arguments in the {meth}`~qiskit.primitives.Sampler.run` method. +- Modify {class}`~qiskit.primitives.Sampler` options. + +### Set keyword arguments for {meth}`~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 {meth}`~qiskit.primitives.Sampler.run` method. You can do this by +passing them as keyword arguments. + +```{eval-rst} +.. testcode:: + + job = sampler.run(qc, shots=2048, seed=123) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) +``` + +### Modify {class}`~qiskit.primitives.Sampler` options + +If you want to keep some configuration values for several runs, it can be better to +change the {class}`~qiskit.primitives.Sampler` options. That way you can use the same +{class}`~qiskit.primitives.Sampler` object as many times as you wish without having to +rewrite the configuration values every time you use {meth}`~qiskit.primitives.Sampler.run`. + +#### Modify existing {class}`~qiskit.primitives.Sampler` + +If you prefer to change the options of an already-defined {class}`~qiskit.primitives.Sampler`, you can use +{meth}`~qiskit.primitives.Sampler.set_options` and introduce the new options as keyword arguments. + +```{eval-rst} +.. testcode:: + + sampler.set_options(shots=2048, seed=123) + + job = sampler.run(qc) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) +``` + +#### Define a new {class}`~qiskit.primitives.Sampler` with the options + +If you prefer to define a new {class}`~qiskit.primitives.Sampler` with new options, you need to +define a `dict` like this one: + +```{eval-rst} +.. testcode:: + + options = {"shots": 2048, "seed": 123} +``` + +And then you can introduce it into your new {class}`~qiskit.primitives.Sampler` with the +`options` argument. + +```{eval-rst} +.. testcode:: + + sampler = Sampler(options=options) + + job = sampler.run(qc) + result = job.result() + print(result) +``` + +```{eval-rst} +.. testoutput:: + + SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) +``` From 56f0042ac7913bf4095f30d887aa5c15191388eb Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 11:02:06 -0400 Subject: [PATCH 02/14] combine mdx files and adjust heading levels --- docs/verify/_toc.json | 4 + docs/verify/simulate-with-primitives.mdx | 639 ++++++++++------------- 2 files changed, 266 insertions(+), 377 deletions(-) diff --git a/docs/verify/_toc.json b/docs/verify/_toc.json index 208ecf41cdc..597e9116a93 100644 --- a/docs/verify/_toc.json +++ b/docs/verify/_toc.json @@ -9,6 +9,10 @@ "title": "Simulators overview", "url": "/verify/simulators" }, + { + "title": "Simulate with Qiskit reference primitives", + "url": "/verify/simulate-with-primitives" + }, { "title": "Simulate with noise", "url": "/verify/noise" diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx index 37ad071c270..db62790933a 100644 --- a/docs/verify/simulate-with-primitives.mdx +++ b/docs/verify/simulate-with-primitives.mdx @@ -1,478 +1,381 @@ --- -title: Simulate using Qiskit reference primitives +title: Simulate with Qiskit reference primitives description: How to compute an expectation value with the Estimator primitive, and how to compute circuit output probabilities with the Sampler primitive --- -# Simulate using Qiskit reference primitives +# Simulate with Qiskit reference primitives -## Compute an expectation value with `Estimator` primitive +## Compute an expectation value with the `Estimator` primitive -This guide shows how to get the expected value of an observable for a given quantum circuit with the {class}`~qiskit.primitives.Estimator` primitive. +This guide shows how to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive. -:::{note} -While this guide uses Qiskit’s reference implementation, the `Estimator` primitive can be run with any provider using {class}`~qiskit.primitives.BackendEstimator` . + + 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). -``` -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 [this page](http://qiskit.org/providers/#primitives) for more details). -::: - -## 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 {mod}`qiskit.quantum_info`. -Among them it is preferable to use {class}`~qiskit.quantum_info.SparsePauliOp`. - -```{eval-rst} -.. testcode:: - - from qiskit.quantum_info import SparsePauliOp + ```python + from qiskit.primitives import BackendEstimator + from import QiskitProvider - observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) -``` + provider = QiskitProvider() + backend = provider.get_backend('backend_name') + estimator = BackendEstimator(backend) + ``` -## Initialize quantum circuit + There are some providers that implement primitives natively (see [this page](https://qiskit.org/providers/#primitives) for more details). + -Then you need to create the {class}`~qiskit.circuit.QuantumCircuit`s for which you want to obtain the expected value. +### Initialize observables -```{eval-rst} -.. plot:: - :include-source: +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). - from qiskit import QuantumCircuit +```python +from qiskit.quantum_info import SparsePauliOp - qc = QuantumCircuit(2) - qc.h(0) - qc.cx(0,1) - qc.draw("mpl") +observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) ``` -```{eval-rst} -.. testsetup:: +### Initialize quantum circuit - # This code is repeated (but hidden) because we will need to use the variables with the extension sphinx.ext.doctest (testsetup/testcode/testoutput directives) - # and we can't reuse the variables from the plot directive above because they are incompatible. - # The plot directive is used to draw the circuit with matplotlib and the code is shown because of the include-source flag. +Then you need to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s for which you want to obtain the expected value. - from qiskit import QuantumCircuit +```python +from qiskit import QuantumCircuit - qc = QuantumCircuit(2) - qc.h(0) - qc.cx(0,1) +qc = QuantumCircuit(2) +qc.h(0) +qc.cx(0,1) +qc.draw("mpl") ``` -:::{note} -The {class}`~qiskit.circuit.QuantumCircuit` you pass to {class}`~qiskit.primitives.Estimator` must not include any measurements. -::: +![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) -## Initialize the `Estimator` + + 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. + -Then, you need to instantiate an {class}`~qiskit.primitives.Estimator`. +### Initialize `Estimator` -```{eval-rst} -.. testcode:: +Then, you need to instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). - from qiskit.primitives import Estimator +```python +from qiskit.primitives import Estimator - estimator = Estimator() +estimator = Estimator() ``` -## Run and get results - -Now that you have defined your `estimator`, you can run your estimation by calling the {meth}`~qiskit.primitives.Estimator.run` method, -which returns an instance of {class}`~.PrimitiveJob` (subclass of {class}`~qiskit.providers.JobV1`). You can get the results from the job (as a {class}`~qiskit.primitives.EstimatorResult` object) -with the {meth}`~qiskit.providers.JobV1.result` method. +### Run and get results -```{eval-rst} -.. testcode:: +Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, +which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) +with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - job = estimator.run(qc, observable) - result = job.result() - print(result) +```python +job = estimator.run(qc, observable) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - EstimatorResult(values=array([4.]), metadata=[{}]) +```python +EstimatorResult(values=array([4.]), metadata=[{}]) ``` -While this example only uses one {class}`~qiskit.circuit.QuantumCircuit` and one observable, if you want to get expectation values for multiple circuits and observables you can -pass a `list` of {class}`~qiskit.circuit.QuantumCircuit`s and a list of `BaseOperator`s to the {meth}`~qiskit.primitives.Estimator.run` method. Both `list`s must have +While 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 +#### Get the expected value -From these results you can extract the expected values with the attribute {attr}`~qiskit.primitives.EstimatorResult.values`. +From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values). -{attr}`~qiskit.primitives.EstimatorResult.values` returns a {class}`numpy.ndarray` +[`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. -```{eval-rst} -.. testcode:: - - exp_value = result.values[0] - print(exp_value) +```python +exp_value = result.values[0] +print(exp_value) ``` -```{eval-rst} -.. testoutput:: - - 3.999999999999999 +```python +3.999999999999999 ``` -## Parameterized circuit with `Estimator` +### Parameterized circuit with `Estimator` -The {class}`~qiskit.primitives.Estimator` primitive can be run with unbound parameterized circuits like the one below. +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. -```{eval-rst} -.. testcode:: - - from qiskit.circuit import Parameter +```python +from qiskit.circuit import Parameter - theta = Parameter('θ') - param_qc = QuantumCircuit(2) - param_qc.ry(theta, 0) - param_qc.cx(0,1) - print(param_qc.draw()) +theta = Parameter('θ') +param_qc = QuantumCircuit(2) +param_qc.ry(theta, 0) +param_qc.cx(0,1) +print(param_qc.draw()) ``` -```{eval-rst} -.. testoutput:: - - ┌───────┐ - q_0: ┤ Ry(θ) ├──■── - └───────┘┌─┴─┐ - q_1: ─────────┤ X ├ - └───┘ +``` + ┌───────┐ +q_0: ┤ Ry(θ) ├──■── + └───────┘┌─┴─┐ +q_1: ─────────┤ X ├ + └───┘ ``` The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. -The `i`-th element of the outer\`\`list\`\` is the set of parameter values +The `i`-th element of the outer `list` is the set of parameter values that corresponds to the `i`-th circuit and observable. -```{eval-rst} -.. testcode:: - - import numpy as np +```python +import numpy as np - parameter_values = [[0], [np.pi/6], [np.pi/2]] +parameter_values = [[0], [np.pi/6], [np.pi/2]] - job = estimator.run([param_qc]*3, [observable]*3, parameter_values=parameter_values) - values = job.result().values +job = estimator.run([param_qc]*3, [observable]*3, parameter_values=parameter_values) +values = job.result().values - for i in range(3): - print(f"Parameter: {parameter_values[i][0]:.5f}\t Expectation value: {values[i]}") +for i in range(3): + print(f"Parameter: {parameter_values[i][0]:.5f}\t Expectation value: {values[i]}") ``` -```{eval-rst} -.. testoutput:: - - Parameter: 0.00000 Expectation value: 2.0 - Parameter: 0.52360 Expectation value: 3.0 - Parameter: 1.57080 Expectation value: 4.0 +``` +Parameter: 0.00000 Expectation value: 2.0 +Parameter: 0.52360 Expectation value: 3.0 +Parameter: 1.57080 Expectation value: 4.0 ``` -## Change run options +### Change run options Your workflow might require tuning primitive run options, such as the amount of shots. -By default, the reference {class}`~qiskit.primitives.Estimator` class performs an exact statevector -calculation based on the {class}`~qiskit.quantum_info.Statevector` class. However, this can be +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 {class}`~qiskit.primitives.Estimator`: +There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator): -- Set keyword arguments in the {meth}`~qiskit.primitives.Estimator.run` method. -- Modify {class}`~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 {meth}`~qiskit.primitives.Estimator.run` +#### 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 {meth}`~qiskit.primitives.Estimator.run` method. You can do this by +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. -```{eval-rst} -.. testcode:: - - 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) ``` -```{eval-rst} -.. testoutput:: - - EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) +```python +EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) ``` -```{eval-rst} -.. testcode:: - - print(result.values[0]) +```python +print(result.values[0]) ``` -```{eval-rst} -.. testoutput:: - - 3.999999998697238 +```python +3.999999998697238 ``` -### Modify {class}`~qiskit.primitives.Estimator` options +#### 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 {class}`~qiskit.primitives.Estimator` options. That way you can use the same -{class}`~qiskit.primitives.Estimator` object as many times as you wish without having to -rewrite the configuration values every time you use {meth}`~qiskit.primitives.Estimator.run`. +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 {class}`~qiskit.primitives.Estimator` +#### Modify existing [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) -If you prefer to change the options of an already-defined {class}`~qiskit.primitives.Estimator`, you can use -{meth}`~qiskit.primitives.Estimator.set_options` and introduce the new options as keyword arguments. +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. -```{eval-rst} -.. testcode:: +```python +estimator.set_options(shots=2048, seed=123) - estimator.set_options(shots=2048, seed=123) - - job = estimator.run(qc, observable) - result = job.result() - print(result) +job = estimator.run(qc, observable) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) +```python +EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) ``` -```{eval-rst} -.. testcode:: - - print(result.values[0]) +```python +print(result.values[0]) ``` -```{eval-rst} -.. testoutput:: - - 3.999999998697238 - +```python +3.999999998697238 ``` -#### Define a new {class}`~qiskit.primitives.Estimator` with the options +#### Define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the options -If you prefer to define a new {class}`~qiskit.primitives.Estimator` with new options, you need to +If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, you need to define a `dict` like this one: -```{eval-rst} -.. testcode:: - - options = {"shots": 2048, "seed": 123} +```python +options = {"shots": 2048, "seed": 123} ``` -And then you can introduce it into your new {class}`~qiskit.primitives.Estimator` with the +And then you can introduce it into your new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the `options` argument. -```{eval-rst} -.. testcode:: - - estimator = Estimator(options=options) +```python +estimator = Estimator(options=options) - job = estimator.run(qc, observable) - result = job.result() - print(result) +job = estimator.run(qc, observable) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) +```python +EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) ``` -```{eval-rst} -.. testcode:: - - print(result.values[0]) +```python +print(result.values[0]) ``` -```{eval-rst} -.. testoutput:: - - 3.999999998697238 +```python +3.999999998697238 ``` - ## Compute circuit output probabilities with `Sampler` primitive -This guide shows how to get the probability distribution of a quantum circuit with the {class}`~qiskit.primitives.Sampler` primitive. - -:::{note} -While this guide uses Qiskit’s reference implementation, the `Sampler` primitive can be run with any provider using {class}`~qiskit.primitives.BackendSampler`. - -``` -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 [this page](http://qiskit.org/providers/#primitives) for more details). -::: +This guide shows how to get the probability distribution of a quantum circuit with the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive. -## Initialize quantum circuits + + 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). -The first step is to create the {class}`~qiskit.circuit.QuantumCircuit`s from which you want to obtain the probability distribution. + ```python + from qiskit.primitives import BackendSampler + from import QiskitProvider -```{eval-rst} -.. plot:: - :include-source: + provider = QiskitProvider() + backend = provider.get_backend('backend_name') + sampler = BackendSampler(backend) + ``` - from qiskit import QuantumCircuit - - qc = QuantumCircuit(2) - qc.h(0) - qc.cx(0,1) - qc.measure_all() - qc.draw("mpl") -``` + There are some providers that implement primitives natively (see [this page](http://qiskit.org/providers/#primitives) for more details). + -```{eval-rst} -.. testsetup:: +### Initialize quantum circuits - # This code is repeated (but hidden) because we will need to use the variables with the extension sphinx.ext.doctest (testsetup/testcode/testoutput directives) - # and we can't reuse the variables from the plot directive above because they are incompatible. - # The plot directive is used to draw the circuit with matplotlib and the code is shown because of the include-source flag. +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 import QuantumCircuit +```python +from qiskit import QuantumCircuit - qc = QuantumCircuit(2) - qc.h(0) - qc.cx(0,1) - qc.measure_all() +qc = QuantumCircuit(2) +qc.h(0) +qc.cx(0,1) +qc.measure_all() +qc.draw("mpl") ``` -:::{note} -The {class}`~qiskit.circuit.QuantumCircuit` you pass to {class}`~qiskit.primitives.Sampler` has to include measurements. -::: +![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) -## Initialize the `Sampler` + +The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) has to include measurements. + -Then, you need to create a {class}`~qiskit.primitives.Sampler` instance. +### Initialize `Sampler` -```{eval-rst} -.. testcode:: +Then, you need to create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance. - from qiskit.primitives import Sampler +```python +from qiskit.primitives import Sampler - sampler = Sampler() +sampler = Sampler() ``` -## Run and get results +### Run and get results -Now that you have defined your `sampler`, you can run it by calling the {meth}`~qiskit.primitives.Sampler.run` method, -which returns an instance of {class}`~.PrimitiveJob` (subclass of {class}`~qiskit.providers.JobV1`). You can get the results from the job (as a {class}`~qiskit.primitives.SamplerResult` object) -with the {meth}`~qiskit.providers.JobV1.result` method. +Now that you have defined your `sampler`, you can 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. -```{eval-rst} -.. testcode:: - - job = sampler.run(qc) - result = job.result() - print(result) +```python +job = sampler.run(qc) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) +```python +SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) ``` -While this example only uses one {class}`~qiskit.circuit.QuantumCircuit`, if you want to sample multiple circuits you can -pass a `list` of {class}`~qiskit.circuit.QuantumCircuit` instances to the {meth}`~qiskit.primitives.Sampler.run` method. +While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), if you want to sample multiple circuits you can +pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. ### Get the probability distribution -From these results you can extract the quasi-probability distributions with the attribute {attr}`~qiskit.primitives.SamplerResult.quasi_dists`. +From these results you can extract the quasi-probability distributions with the attribute [`qiskit.primitives.Sampler.quasi_dists`](../api/qiskit/qiskit.primitives.Sampler#quasi_dists). -Even though there is only one circuit in this example, {attr}`~qiskit.primitives.SamplerResult.quasi_dists` returns a list of {class}`~qiskit.result.QuasiDistribution`s. +Even though there is only one circuit in this example, [`qiskit.primitives.Sampler.quasi_dists`](../api/qiskit/qiskit.primitives.Sampler#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. -:::{note} + A quasi-probability distribution differs from a probability distribution in that negative values are also allowed. However the quasi-probabilities must sum up to 1 like probabilities. Negative quasi-probabilities may appear when using error mitigation techniques. -::: + -```{eval-rst} -.. testcode:: - - quasi_dist = result.quasi_dists[0] - print(quasi_dist) +```python +quasi_dist = result.quasi_dists[0] +print(quasi_dist) ``` -```{eval-rst} -.. testoutput:: - - {0: 0.4999999999999999, 3: 0.4999999999999999} +```python +{0: 0.4999999999999999, 3: 0.4999999999999999} ``` #### Probability distribution with binary outputs If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the -{meth}`~qiskit.result.QuasiDistribution.binary_probabilities` method. +[`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. -```{eval-rst} -.. testcode:: - - print(quasi_dist.binary_probabilities()) +```python +print(quasi_dist.binary_probabilities()) ``` -```{eval-rst} -.. testoutput:: - - {'00': 0.4999999999999999, '11': 0.4999999999999999} +```python +{'00': 0.4999999999999999, '11': 0.4999999999999999} ``` -## Parameterized circuit with `Sampler` +### Parameterized circuit with `Sampler` -The {class}`~qiskit.primitives.Sampler` primitive can be run with unbound parameterized circuits like the one below. +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. -```{eval-rst} -.. testcode:: +```python +from qiskit.circuit import Parameter - from qiskit.circuit import Parameter - - theta = Parameter('θ') - param_qc = QuantumCircuit(2) - param_qc.ry(theta, 0) - param_qc.cx(0,1) - param_qc.measure_all() - print(param_qc.draw()) +theta = Parameter('θ') +param_qc = QuantumCircuit(2) +param_qc.ry(theta, 0) +param_qc.cx(0,1) +param_qc.measure_all() +print(param_qc.draw()) ``` -```{eval-rst} -.. testoutput:: - - ┌───────┐ ░ ┌─┐ - q_0: ┤ Ry(θ) ├──■───░─┤M├─── - └───────┘┌─┴─┐ ░ └╥┘┌─┐ - q_1: ─────────┤ X ├─░──╫─┤M├ - └───┘ ░ ║ └╥┘ - meas: 2/══════════════════╩══╩═ - 0 1 +``` + ┌───────┐ ░ ┌─┐ + q_0: ┤ Ry(θ) ├──■───░─┤M├─── + └───────┘┌─┴─┐ ░ └╥┘┌─┐ + q_1: ─────────┤ X ├─░──╫─┤M├ + └───┘ ░ ║ └╥┘ +meas: 2/══════════════════╩══╩═ + 0 1 ``` The main difference from the previous case is that now you need to specify the sets of parameter values @@ -480,116 +383,98 @@ for which you want to evaluate the expectation value as a `list` of `list`s of ` The `i`-th element of the outer `list` is the set of parameter values that corresponds to the `i`-th circuit. -```{eval-rst} -.. testcode:: - - import numpy as np +```python +import numpy as np - parameter_values = [[0], [np.pi/6], [np.pi/2]] +parameter_values = [[0], [np.pi/6], [np.pi/2]] - job = sampler.run([param_qc]*3, parameter_values=parameter_values) - dists = job.result().quasi_dists +job = sampler.run([param_qc]*3, parameter_values=parameter_values) +dists = job.result().quasi_dists - for i in range(3): - print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}") +for i in range(3): + print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}") ``` -```{eval-rst} -.. testoutput:: - - 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} +``` +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 +### Change run options Your workflow might require tuning primitive run options, such as the amount of shots. -By default, the reference {class}`~qiskit.primitives.Sampler` class performs an exact statevector -calculation based on the {class}`~qiskit.quantum_info.Statevector` class. However, this can be +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 {class}`~qiskit.primitives.Sampler`: +There are two main ways of setting options in the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler): -- Set keyword arguments in the {meth}`~qiskit.primitives.Sampler.run` method. -- Modify {class}`~qiskit.primitives.Sampler` options. +- 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 {meth}`~qiskit.primitives.Sampler.run` +#### 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 {meth}`~qiskit.primitives.Sampler.run` method. You can do this by +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. -```{eval-rst} -.. testcode:: - - job = sampler.run(qc, shots=2048, seed=123) - result = job.result() - print(result) +```python +job = sampler.run(qc, shots=2048, seed=123) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) +```python +SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) ``` -### Modify {class}`~qiskit.primitives.Sampler` options +#### 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 {class}`~qiskit.primitives.Sampler` options. That way you can use the same -{class}`~qiskit.primitives.Sampler` object as many times as you wish without having to -rewrite the configuration values every time you use {meth}`~qiskit.primitives.Sampler.run`. +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 {class}`~qiskit.primitives.Sampler` +#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) -If you prefer to change the options of an already-defined {class}`~qiskit.primitives.Sampler`, you can use -{meth}`~qiskit.primitives.Sampler.set_options` and introduce the new options as keyword arguments. +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. -```{eval-rst} -.. testcode:: +```python +sampler.set_options(shots=2048, seed=123) - sampler.set_options(shots=2048, seed=123) - - job = sampler.run(qc) - result = job.result() - print(result) +job = sampler.run(qc) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) +```python +SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) ``` -#### Define a new {class}`~qiskit.primitives.Sampler` with the options +#### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options -If you prefer to define a new {class}`~qiskit.primitives.Sampler` with new options, you need to +If you prefer to define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options, you need to define a `dict` like this one: -```{eval-rst} -.. testcode:: - - options = {"shots": 2048, "seed": 123} +```python +options = {"shots": 2048, "seed": 123} ``` -And then you can introduce it into your new {class}`~qiskit.primitives.Sampler` with the +And then you can introduce it into your new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the `options` argument. -```{eval-rst} -.. testcode:: - - sampler = Sampler(options=options) +```python +sampler = Sampler(options=options) - job = sampler.run(qc) - result = job.result() - print(result) +job = sampler.run(qc) +result = job.result() +print(result) ``` -```{eval-rst} -.. testoutput:: - - SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) +```python +SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) ``` From b2dc4f0ef93e74acf8071353e639fba2c27870d9 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 11:12:40 -0400 Subject: [PATCH 03/14] copyediting estimator section --- docs/verify/simulate-with-primitives.mdx | 66 +++++++++--------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx index db62790933a..177cd4c3b69 100644 --- a/docs/verify/simulate-with-primitives.mdx +++ b/docs/verify/simulate-with-primitives.mdx @@ -35,9 +35,9 @@ from qiskit.quantum_info import SparsePauliOp observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) ``` -### Initialize quantum circuit +### Initialize QuantumCircuit -Then you need to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s for which you want to obtain the expected value. +Next, create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s for which you want to obtain the expected value. ```python from qiskit import QuantumCircuit @@ -56,7 +56,7 @@ qc.draw("mpl") ### Initialize `Estimator` -Then, you need to instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). +Next, instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). ```python from qiskit.primitives import Estimator @@ -80,16 +80,14 @@ print(result) EstimatorResult(values=array([4.]), metadata=[{}]) ``` -While 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. +This example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable. If you want to get expectation values for multiple circuits and observables, you can pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have the same length. #### Get the expected value From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values). [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray` -whose `i`-th element is the expectation value corresponding to the `i`-th circuit and `i`-th observable. +whose `i`th element is the expectation value corresponding to the `i`th circuit and `i`th observable. ```python exp_value = result.values[0] @@ -103,8 +101,7 @@ print(exp_value) ### 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. +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 @@ -124,10 +121,8 @@ q_1: ─────────┤ X ├ └───┘ ``` -The main difference with the previous case is that now you need to specify the sets of parameter values -for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. -The `i`-th element of the outer `list` is the set of parameter values -that corresponds to the `i`-th circuit and observable. +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 import numpy as np @@ -149,12 +144,9 @@ Parameter: 1.57080 Expectation value: 4.0 ### Change run options -Your workflow might require tuning primitive run options, such as the amount of shots. +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. +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): @@ -163,9 +155,7 @@ There are two main ways of setting options in the [`qiskit.primitives.Estimator` #### 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. +If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by passing them as keyword arguments. ```python job = estimator.run(qc, observable, shots=2048, seed=123) @@ -187,15 +177,12 @@ print(result.values[0]) #### 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 +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. +If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments. ```python estimator.set_options(shots=2048, seed=123) @@ -219,15 +206,13 @@ print(result.values[0]) #### 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, you need to -define a `dict` like this one: +If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, define a `dict` like this one: ```python options = {"shots": 2048, "seed": 123} ``` -And then you can introduce it into your new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the -`options` argument. +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) @@ -321,7 +306,7 @@ pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit. From these results you can extract the quasi-probability distributions with the attribute [`qiskit.primitives.Sampler.quasi_dists`](../api/qiskit/qiskit.primitives.Sampler#quasi_dists). Even though there is only one circuit in this example, [`qiskit.primitives.Sampler.quasi_dists`](../api/qiskit/qiskit.primitives.Sampler#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. +`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. @@ -380,8 +365,8 @@ meas: 2/══════════════════╩══╩═ 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. +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 @@ -403,7 +388,7 @@ Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.499999999999999 ### Change run options -Your workflow might require tuning primitive run options, such as the amount of shots. +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 @@ -433,15 +418,12 @@ SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shot #### 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 +If you want to keep some configuration values for several runs, it can be better to change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run). #### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) -If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use -[`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments. +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) @@ -457,15 +439,13 @@ 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, you need to -define a `dict` like this one: +If you prefer to define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options, define a `dict` like this one: ```python options = {"shots": 2048, "seed": 123} ``` -And then you can introduce it into your new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the -`options` argument. +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) From 40c57e3e13764f56344bf4d0730f6272e9f5fb50 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 11:16:11 -0400 Subject: [PATCH 04/14] copyediting the sampler section --- docs/verify/simulate-with-primitives.mdx | 33 ++++++++---------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx index 177cd4c3b69..5f98351acda 100644 --- a/docs/verify/simulate-with-primitives.mdx +++ b/docs/verify/simulate-with-primitives.mdx @@ -252,7 +252,7 @@ This guide shows how to get the probability distribution of a quantum circuit wi There are some providers that implement primitives natively (see [this page](http://qiskit.org/providers/#primitives) for more details). -### Initialize quantum circuits +### Initialize QuantumCircuit The first step is to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s from which you want to obtain the probability distribution. @@ -269,12 +269,12 @@ qc.draw("mpl") ![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) -The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) has to include measurements. +The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) must include measurements. ### Initialize `Sampler` -Then, you need to create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance. +Next, create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance. ```python from qiskit.primitives import Sampler @@ -284,9 +284,7 @@ sampler = Sampler() ### Run and get results -Now that you have defined your `sampler`, you can 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. +Now that you have defined your `sampler`, run it by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. ```python job = sampler.run(qc) @@ -298,8 +296,7 @@ print(result) SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) ``` -While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), if you want to sample multiple circuits you can -pass 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. +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 @@ -310,7 +307,7 @@ Even though there is only one circuit in this example, [`qiskit.primitives.Sampl 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. +However, the quasi-probabilities must sum up to 1 like probabilities. Negative quasi-probabilities may appear when using error mitigation techniques. @@ -325,8 +322,7 @@ print(quasi_dist) #### Probability distribution with binary outputs -If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the -[`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. +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()) @@ -339,8 +335,7 @@ print(quasi_dist.binary_probabilities()) ### 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. +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 @@ -363,10 +358,7 @@ meas: 2/══════════════════╩══╩═ 0 1 ``` -The main difference from the previous case is that now you need to specify the sets of parameter values -for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. -The `i`th element of the outer `list` is the set of parameter values -that corresponds to the `i`th circuit. +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 @@ -402,9 +394,7 @@ There are two main ways of setting options in the [`qiskit.primitives.Sampler`]( #### 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. +If you only want to change the settings for a specific run, it can be more convenient to set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by passing them as keyword arguments. ```python job = sampler.run(qc, shots=2048, seed=123) @@ -418,8 +408,7 @@ SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shot #### 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). +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) From 243c23b2c9773d6f477b4d32cb2fdf8d4325c452 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 11:17:15 -0400 Subject: [PATCH 05/14] rmv reference from page name and toc --- docs/verify/_toc.json | 2 +- docs/verify/simulate-with-primitives.mdx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/verify/_toc.json b/docs/verify/_toc.json index 597e9116a93..1858739d798 100644 --- a/docs/verify/_toc.json +++ b/docs/verify/_toc.json @@ -10,7 +10,7 @@ "url": "/verify/simulators" }, { - "title": "Simulate with Qiskit reference primitives", + "title": "Simulate with Qiskit primitives", "url": "/verify/simulate-with-primitives" }, { diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx index 5f98351acda..0fd1ce52413 100644 --- a/docs/verify/simulate-with-primitives.mdx +++ b/docs/verify/simulate-with-primitives.mdx @@ -1,9 +1,9 @@ --- -title: Simulate with Qiskit reference primitives -description: How to compute an expectation value with the Estimator primitive, and how to compute circuit output probabilities with the Sampler primitive +title: Simulate with Qiskit primitives +description: Simulate with Qiskit reference primitives. How to compute an expectation value with the Estimator primitive, and how to compute circuit output probabilities with the Sampler primitive --- -# Simulate with Qiskit reference primitives +# Simulate with Qiskit primitives ## Compute an expectation value with the `Estimator` primitive From 8f9f587d6d6d6ed06cff1949e891998c483efdfc Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 11:38:00 -0400 Subject: [PATCH 06/14] add intro pph --- docs/run/primitives.mdx | 3 ++- docs/verify/simulate-with-primitives.mdx | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/run/primitives.mdx b/docs/run/primitives.mdx index 9a6fd952ede..70c9f1aa0da 100644 --- a/docs/run/primitives.mdx +++ b/docs/run/primitives.mdx @@ -45,12 +45,13 @@ An expectation value of an observable could be the target quantity in scenarios The open-source primitives contain the base classes (to define interfaces) and a reference implementation. The Qiskit Runtime primitives provide a more sophisticated implementation (such as with error mitigation) as a cloud-based service. + ## Where should I import the primitive from? There are different primitive implementations in the ``qiskit``, ``qiskit_aer``, and ``qiskit_ibm_runtime`` libraries. Each implementation serves a specific purpose: -* The primitives in ``qiskit`` can perform local state vector simulations - useful for quickly prototyping algorithms. +* The primitives in ``qiskit`` can perform local statevector simulations - useful for quickly prototyping algorithms. * The `qiskit.primitives` module enables the development of primitive-style quantum programs and was specifically designed to simplify switching between different types of backends. The module provides three separate classes for each primitive type: 1. `Sampler` and `Estimator` diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx index 0fd1ce52413..f59b540f48d 100644 --- a/docs/verify/simulate-with-primitives.mdx +++ b/docs/verify/simulate-with-primitives.mdx @@ -5,9 +5,11 @@ description: Simulate with Qiskit reference primitives. How to compute an expect # Simulate with Qiskit primitives +The reference primitives in Qiskit can perform local statevector simulations, which is useful for quickly prototyping algorithms. The `Estimator` primitive can compute an expectation value, and the `Sampler` primitive can compute circuit output probabilities. For import instructions, see the topic [Where should I import the primitive from?](../run/primitives#import-primitives) + ## Compute an expectation value with the `Estimator` primitive -This guide shows how to get the expected value of an observable for a given quantum circuit with the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.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 Qiskit’s reference implementation, the `Estimator` primitive can be run with any provider using [`qiskit.primitives.BackendEstimator`](../api/qiskit/qiskit.primitives.BackendEstimator). @@ -235,7 +237,7 @@ print(result.values[0]) ``` ## Compute circuit output probabilities with `Sampler` primitive -This guide shows how to get the probability distribution of a quantum circuit with the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.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). From 76dc51abcfe403d6ffb62bf9c5861b31186db5c1 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 12:05:49 -0400 Subject: [PATCH 07/14] update intro and change sim overview to more fitting title --- docs/verify/_toc.json | 2 +- docs/verify/index.mdx | 2 +- docs/verify/simulators.mdx | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/verify/_toc.json b/docs/verify/_toc.json index 1858739d798..80ab0c93c0b 100644 --- a/docs/verify/_toc.json +++ b/docs/verify/_toc.json @@ -6,7 +6,7 @@ "url": "/verify" }, { - "title": "Simulators overview", + "title": "IBM Quantum simulators", "url": "/verify/simulators" }, { diff --git a/docs/verify/index.mdx b/docs/verify/index.mdx index 49decf10e9a..587e845683f 100644 --- a/docs/verify/index.mdx +++ b/docs/verify/index.mdx @@ -6,7 +6,7 @@ description: Introduction to the Verify phase In the verify phase, you test your quantum programs by running them on simulated devices and exploring their performance under realistic device [noise models](https://qiskit.org/ecosystem/aer/apidocs/aer_noise.html). This allows you to validate them before sending them to a physical system. This phase consists of the following steps: -1. Run your program on a [quantum simulator](simulators). +1. Run your program on a quantum simulator, using [Qiskit reference primitives](simulate-with-primitives) or [IBM Quantum cloud-based simulators](simulators). 1. [Add noise to your simulation](noise). 2. Optionally [create your own noise model](building_noise_models). diff --git a/docs/verify/simulators.mdx b/docs/verify/simulators.mdx index 4246835d8b7..f3a61eecc9f 100644 --- a/docs/verify/simulators.mdx +++ b/docs/verify/simulators.mdx @@ -1,11 +1,11 @@ --- -title: Simulators overview -description: Overview of simulators +title: IBM Quantum simulators +description: Overview of IBM Quantum cloud-based simulators --- -# Simulators overview +# IBM Quantum simulators -This page gives details about the IBM Quantum cloud-based simulators. For information about the Qiskit built-in simulator, see the [Python-based simulators page in the API reference.](https://docs.quantum-computing.ibm.com/api/qiskit/providers_basicaer) +This page gives details about the IBM Quantum cloud-based simulators. For information about the Qiskit built-in simulator, see the [Python-based simulators page in the API reference.](https://docs.quantum-computing.ibm.com/api/qiskit/providers_basicaer) You can also use the [Qiskit reference primitives](simulate-with-primitives) for local statevector simulation. IBM Quantum features a collection of high-performance simulators for prototyping quantum circuits and algorithms. From 6ca4fb63a2f5341017ea85d994176691fa67d75e Mon Sep 17 00:00:00 2001 From: abbycross Date: Tue, 17 Oct 2023 12:41:52 -0400 Subject: [PATCH 08/14] Update docs/verify/simulate-with-primitives.mdx Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> --- docs/verify/simulate-with-primitives.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-primitives.mdx index f59b540f48d..f044a490462 100644 --- a/docs/verify/simulate-with-primitives.mdx +++ b/docs/verify/simulate-with-primitives.mdx @@ -5,7 +5,9 @@ description: Simulate with Qiskit reference primitives. How to compute an expect # Simulate with Qiskit primitives -The reference primitives in Qiskit can perform local statevector simulations, which is useful for quickly prototyping algorithms. The `Estimator` primitive can compute an expectation value, and the `Sampler` primitive can compute circuit output probabilities. For import instructions, see the topic [Where should I import the primitive from?](../run/primitives#import-primitives) +The reference primitives in Qiskit can perform local statevector simulations, which is useful for quickly prototyping algorithms. + +The `Estimator` primitive can compute an expectation value, and the `Sampler` primitive can compute circuit output probabilities. For import instructions, see the topic [Where should I import the primitive from?](../run/primitives#import-primitives) ## Compute an expectation value with the `Estimator` primitive From cfa04f672bb80c6d248aaf408229b612398e740c Mon Sep 17 00:00:00 2001 From: abbycross Date: Tue, 17 Oct 2023 12:43:34 -0400 Subject: [PATCH 09/14] link internally to api --- docs/verify/simulators.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verify/simulators.mdx b/docs/verify/simulators.mdx index f3a61eecc9f..32693a46137 100644 --- a/docs/verify/simulators.mdx +++ b/docs/verify/simulators.mdx @@ -5,7 +5,7 @@ description: Overview of IBM Quantum cloud-based simulators # IBM Quantum simulators -This page gives details about the IBM Quantum cloud-based simulators. For information about the Qiskit built-in simulator, see the [Python-based simulators page in the API reference.](https://docs.quantum-computing.ibm.com/api/qiskit/providers_basicaer) You can also use the [Qiskit reference primitives](simulate-with-primitives) for local statevector simulation. +This page gives details about the IBM Quantum cloud-based simulators. For information about the Qiskit built-in simulator, see the [Python-based simulators page in the API reference.](../api/qiskit/providers_basicaer) You can also use the [Qiskit reference primitives](simulate-with-primitives) for local statevector simulation. IBM Quantum features a collection of high-performance simulators for prototyping quantum circuits and algorithms. From 849be467e0eb2f6453832b3c9323741b232fcfb8 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 12:45:27 -0400 Subject: [PATCH 10/14] rename urls --- docs/verify/_toc.json | 4 ++-- docs/verify/{simulators.mdx => cloud-based-simulators.mdx} | 0 ...ith-primitives.mdx => simulate-with-qiskit-primitives.mdx} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename docs/verify/{simulators.mdx => cloud-based-simulators.mdx} (100%) rename docs/verify/{simulate-with-primitives.mdx => simulate-with-qiskit-primitives.mdx} (100%) diff --git a/docs/verify/_toc.json b/docs/verify/_toc.json index 80ab0c93c0b..5d7d1881035 100644 --- a/docs/verify/_toc.json +++ b/docs/verify/_toc.json @@ -7,11 +7,11 @@ }, { "title": "IBM Quantum simulators", - "url": "/verify/simulators" + "url": "/verify/cloud-based-simulators" }, { "title": "Simulate with Qiskit primitives", - "url": "/verify/simulate-with-primitives" + "url": "/verify/simulate-with-qiskit-primitives" }, { "title": "Simulate with noise", diff --git a/docs/verify/simulators.mdx b/docs/verify/cloud-based-simulators.mdx similarity index 100% rename from docs/verify/simulators.mdx rename to docs/verify/cloud-based-simulators.mdx diff --git a/docs/verify/simulate-with-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx similarity index 100% rename from docs/verify/simulate-with-primitives.mdx rename to docs/verify/simulate-with-qiskit-primitives.mdx From 2ced569e4b260586bebf334633f12ddf1b8a5686 Mon Sep 17 00:00:00 2001 From: abbycross Date: Tue, 17 Oct 2023 12:55:37 -0400 Subject: [PATCH 11/14] Update docs/verify/simulate-with-qiskit-primitives.mdx --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f044a490462..8aadf700073 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -7,7 +7,9 @@ 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. For import instructions, see the topic [Where should I import the primitive from?](../run/primitives#import-primitives) +The `Estimator` primitive can compute an expectation value, and the `Sampler` primitive can compute circuit output probabilities. + +For import instructions, see the topic [Where should I import the primitive from?](../run/primitives#import-primitives) ## Compute an expectation value with the `Estimator` primitive From f9a987efe8ca607e8cc022455d7547117d5658a0 Mon Sep 17 00:00:00 2001 From: ABBY CROSS Date: Tue, 17 Oct 2023 13:05:35 -0400 Subject: [PATCH 12/14] adjust alignment in drawings --- .../simulate-with-qiskit-primitives.mdx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index f044a490462..b895eb28cf9 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -118,11 +118,11 @@ print(param_qc.draw()) ``` ``` - ┌───────┐ + ┌───────┐ q_0: ┤ Ry(θ) ├──■── - └───────┘┌─┴─┐ + └───────┘┌─┴─┐ q_1: ─────────┤ X ├ - └───┘ + └───┘ ``` The main difference with the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. @@ -353,13 +353,13 @@ print(param_qc.draw()) ``` ``` - ┌───────┐ ░ ┌─┐ - q_0: ┤ Ry(θ) ├──■───░─┤M├─── - └───────┘┌─┴─┐ ░ └╥┘┌─┐ - q_1: ─────────┤ X ├─░──╫─┤M├ - └───┘ ░ ║ └╥┘ -meas: 2/══════════════════╩══╩═ - 0 1 + ┌───────┐ ░ ┌─┐ + q_0: ┤ Ry(θ) ├──■───░─┤M├─── + └───────┘┌─┴─┐ ░ └╥┘┌─┐ + q_1: ─────────┤ X ├─░──╫─┤M├ + └───┘ ░ ║ └╥┘ + meas: 2/══════════════════╩══╩═ + 0 1 ``` The main difference from the previous case is that now you need to specify the sets of parameter values for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. The `i`th element of the outer `list` is the set of parameter values that corresponds to the `i`th circuit. From 7a3bb79033d760e953daae51090167041575858c Mon Sep 17 00:00:00 2001 From: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:08:54 -0400 Subject: [PATCH 13/14] Reorganize files --- docs/verify/simulate-with-qiskit-primitives.mdx | 4 ++-- .../estimator-initialize.png} | Bin .../sampler-initialize.png} | Bin 3 files changed, 2 insertions(+), 2 deletions(-) rename public/images/verify/{use_estimator/initialize.png => simulate-with-qiskit-primitives/estimator-initialize.png} (100%) rename public/images/verify/{use_sampler/initialize.png => simulate-with-qiskit-primitives/sampler-initialize.png} (100%) diff --git a/docs/verify/simulate-with-qiskit-primitives.mdx b/docs/verify/simulate-with-qiskit-primitives.mdx index 8aadf700073..a95d358311c 100644 --- a/docs/verify/simulate-with-qiskit-primitives.mdx +++ b/docs/verify/simulate-with-qiskit-primitives.mdx @@ -54,7 +54,7 @@ qc.cx(0,1) qc.draw("mpl") ``` -![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) +![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png) 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. @@ -272,7 +272,7 @@ qc.measure_all() qc.draw("mpl") ``` -![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) +![Initial QuantumCircuit](/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png) The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) must include measurements. diff --git a/public/images/verify/use_estimator/initialize.png b/public/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png similarity index 100% rename from public/images/verify/use_estimator/initialize.png rename to public/images/verify/simulate-with-qiskit-primitives/estimator-initialize.png diff --git a/public/images/verify/use_sampler/initialize.png b/public/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png similarity index 100% rename from public/images/verify/use_sampler/initialize.png rename to public/images/verify/simulate-with-qiskit-primitives/sampler-initialize.png From ddceea06241afbbb8da9ea09a375c66934625a96 Mon Sep 17 00:00:00 2001 From: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:14:47 -0400 Subject: [PATCH 14/14] Remove original guides Co-authored-by: Guillermo-Mijares-Vilarino <106545082+Guillermo-Mijares-Vilarino@users.noreply.github.com> --- docs/verify/__use_estimator.mdx | 248 -------------------------------- docs/verify/__use_sampler.mdx | 235 ------------------------------ 2 files changed, 483 deletions(-) delete mode 100644 docs/verify/__use_estimator.mdx delete mode 100644 docs/verify/__use_sampler.mdx diff --git a/docs/verify/__use_estimator.mdx b/docs/verify/__use_estimator.mdx deleted file mode 100644 index 3eabf7b0c13..00000000000 --- a/docs/verify/__use_estimator.mdx +++ /dev/null @@ -1,248 +0,0 @@ ---- -title: Estimator primitive -description: How to compute an expectation value with the `Estimator` primitive ---- - -# Compute an expectation value with `Estimator` primitive - -This guide shows how 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). - - ```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 [this page](https://qiskit.org/providers/#primitives) for more details). - - -## Initialize observables - -The first step is to define the observables whose expected value you want to compute. Each observable can be any `BaseOperator`, like the operators from [`qiskit.quantum_info`](../api/qiskit/quantum_info). -Among them it is preferable to use [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). - -```python -from qiskit.quantum_info import SparsePauliOp - -observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1]) -``` - -## Initialize quantum circuit - -Then you need to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s for which you want to obtain the expected value. - -```python -from qiskit import QuantumCircuit - -qc = QuantumCircuit(2) -qc.h(0) -qc.cx(0,1) -qc.draw("mpl") -``` - -![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) - - - 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 the `Estimator` - -Then, you need to instantiate an [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator). - -```python -from qiskit.primitives import Estimator - -estimator = Estimator() -``` - -## Run and get results - -Now that you have defined your `estimator`, you can run your estimation by calling the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method, -which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.EstimatorResult`](../api/qiskit/qiskit.primitives.EstimatorResult) object) -with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - -```python -job = estimator.run(qc, observable) -result = job.result() -print(result) -``` - -```python -EstimatorResult(values=array([4.]), metadata=[{}]) -``` - -While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) and one observable, if you want to get expectation values for multiple circuits and observables you can -pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s and a list of `BaseOperator`s to the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. Both `list`s must have -the same length. - -### Get the expected value - -From these results you can extract the expected values with the attribute [`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values). - -[`qiskit.primitives.EstimatorResult.values`](../api/qiskit/qiskit.primitives.EstimatorResult#values) returns a `numpy.ndarray` -whose `i`-th element is the expectation value corresponding to the `i`-th circuit and `i`-th observable. - -```python -exp_value = result.values[0] -print(exp_value) -``` - -```python -3.999999999999999 -``` - -## Parameterized circuit with `Estimator` - -The [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) primitive can be run with unbound parameterized circuits like the one below. -You can also manually bind values to the parameters of the circuit and follow the steps -of the previous example. - -```python -from qiskit.circuit import Parameter - -theta = Parameter('θ') -param_qc = QuantumCircuit(2) -param_qc.ry(theta, 0) -param_qc.cx(0,1) -print(param_qc.draw()) -``` - -``` - ┌───────┐ -q_0: ┤ Ry(θ) ├──■── - └───────┘┌─┴─┐ -q_1: ─────────┤ X ├ - └───┘ -``` - -The main difference with the previous case is that now you need to specify the sets of parameter values -for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. -The `i`-th element of the outer `list` is the set of parameter values -that corresponds to the `i`-th circuit and observable. - -```python -import numpy as np - -parameter_values = [[0], [np.pi/6], [np.pi/2]] - -job = estimator.run([param_qc]*3, [observable]*3, parameter_values=parameter_values) -values = job.result().values - -for i in range(3): - print(f"Parameter: {parameter_values[i][0]:.5f}\t Expectation value: {values[i]}") -``` - -``` -Parameter: 0.00000 Expectation value: 2.0 -Parameter: 0.52360 Expectation value: 3.0 -Parameter: 1.57080 Expectation value: 4.0 -``` - -## Change run options - -Your workflow might require tuning primitive run options, such as the amount of shots. - -By default, the reference [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) class performs an exact statevector -calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be -modified to include shot noise if the number of `shots` is set. -For reproducibility purposes, a `seed` will also be set in the following examples. - -There are two main ways of setting options in the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator): - -- Set keyword arguments in the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. -- Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. - -### Set keyword arguments for [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) - -If you only want to change the settings for a specific run, it can be more convenient to -set the options inside the [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run) method. You can do this by -passing them as keyword arguments. - -```python -job = estimator.run(qc, observable, shots=2048, seed=123) -result = job.result() -print(result) -``` - -```python -EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) -``` - -```python -print(result.values[0]) -``` - -```python -3.999999998697238 -``` - -### Modify [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options - -If you want to keep some configuration values for several runs, it can be better to -change the [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) options. That way you can use the same -[`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) object as many times as you wish without having to -rewrite the configuration values every time you use [`qiskit.primitives.Estimator.run`](../api/qiskit/qiskit.primitives.Estimator#run). - -#### Modify existing [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) - -If you prefer to change the options of an already-defined [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator), you can use -the method [`qiskit.primitives.Estimator.set_options`](../api/qiskit/qiskit.primitives.Estimator#set_options) and introduce the new options as keyword arguments. - -```python -estimator.set_options(shots=2048, seed=123) - -job = estimator.run(qc, observable) -result = job.result() -print(result) -``` - -```python -EstimatorResult(values=array([4.]), metadata=[{'variance': 3.552713678800501e-15, 'shots': 2048}]) -``` - -```python -print(result.values[0]) -``` - -```python -3.999999998697238 -``` - -#### Define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with the options - -If you prefer to define a new [`qiskit.primitives.Estimator`](../api/qiskit/qiskit.primitives.Estimator) with new options, you need to -define a `dict` like this one: - -```python -options = {"shots": 2048, "seed": 123} -``` - -And then you can 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 -``` diff --git a/docs/verify/__use_sampler.mdx b/docs/verify/__use_sampler.mdx deleted file mode 100644 index 0951d6655ef..00000000000 --- a/docs/verify/__use_sampler.mdx +++ /dev/null @@ -1,235 +0,0 @@ ---- -title: Sampler primitive -description: How to compute circuit output probabilities with the `Sampler` primitive ---- - -# Compute circuit output probabilities with `Sampler` primitive - -This guide shows how 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). - - ```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 [this page](http://qiskit.org/providers/#primitives) for more details). - - -## Initialize quantum circuits - -The first step is to create the [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)s from which you want to obtain the probability distribution. - -```python -from qiskit import QuantumCircuit - -qc = QuantumCircuit(2) -qc.h(0) -qc.cx(0,1) -qc.measure_all() -qc.draw("mpl") -``` - -![Initial QuantumCircuit](/images/verify/use_estimator/initialize.png) - - -The [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) you pass to [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) has to include measurements. - - -## Initialize the `Sampler` - -Then, you need to create a [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) instance. - -```python -from qiskit.primitives import Sampler - -sampler = Sampler() -``` - -## Run and get results - -Now that you have defined your `sampler`, you can run it by calling the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method, -which returns an instance of [`qiskit.providers.JobV1`](../api/qiskit/qiskit.providers.JobV1). You can get the results from the job (as a [`qiskit.primitives.SamplerResult`](../api/qiskit/qiskit.primitives.SamplerResult) object) -with the [`qiskit.providers.JobV1.result`](../api/qiskit/qiskit.providers.JobV1#result) method. - -```python -job = sampler.run(qc) -result = job.result() -print(result) -``` - -```python -SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}]) -``` - -While this example only uses one [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit), if you want to sample multiple circuits you can -pass a `list` of [`qiskit.circuit.QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) instances to the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. - -### Get the probability distribution - -From these results you can extract the quasi-probability distributions with the attribute [`qiskit.primitives.Sampler.quasi_dists`](../api/qiskit/qiskit.primitives.Sampler#quasi_dists). - -Even though there is only one circuit in this example, [`qiskit.primitives.Sampler.quasi_dists`](../api/qiskit/qiskit.primitives.Sampler#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. -However the quasi-probabilities must sum up to 1 like probabilities. -Negative quasi-probabilities may appear when using error mitigation techniques. - - -```python -quasi_dist = result.quasi_dists[0] -print(quasi_dist) -``` - -```python -{0: 0.4999999999999999, 3: 0.4999999999999999} -``` - -#### Probability distribution with binary outputs - -If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the -[`qiskit.result.QuasiDistribution.binary_probabilities`](../api/qiskit/qiskit.result.QuasiDistribution#binary_probabilities) method. - -```python -print(quasi_dist.binary_probabilities()) -``` - -```python -{'00': 0.4999999999999999, '11': 0.4999999999999999} -``` - -## Parameterized circuit with `Sampler` - -The [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) primitive can be run with unbound parameterized circuits like the one below. -You can also manually bind values to the parameters of the circuit and follow the steps -of the previous example. - -```python -from qiskit.circuit import Parameter - -theta = Parameter('θ') -param_qc = QuantumCircuit(2) -param_qc.ry(theta, 0) -param_qc.cx(0,1) -param_qc.measure_all() -print(param_qc.draw()) -``` - -``` - ┌───────┐ ░ ┌─┐ - q_0: ┤ Ry(θ) ├──■───░─┤M├─── - └───────┘┌─┴─┐ ░ └╥┘┌─┐ - q_1: ─────────┤ X ├─░──╫─┤M├ - └───┘ ░ ║ └╥┘ -meas: 2/══════════════════╩══╩═ - 0 1 -``` - -The main difference from the previous case is that now you need to specify the sets of parameter values -for which you want to evaluate the expectation value as a `list` of `list`s of `float`s. -The `i`-th element of the outer `list` is the set of parameter values -that corresponds to the `i`-th circuit. - -```python -import numpy as np - -parameter_values = [[0], [np.pi/6], [np.pi/2]] - -job = sampler.run([param_qc]*3, parameter_values=parameter_values) -dists = job.result().quasi_dists - -for i in range(3): - print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}") -``` - -``` -Parameter: 0.00000 Probabilities: {0: 1.0} -Parameter: 0.52360 Probabilities: {0: 0.9330127018922194, 3: 0.0669872981077807} -Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.4999999999999999} -``` - -## Change run options - -Your workflow might require tuning primitive run options, such as the amount of shots. - -By default, the reference [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) class performs an exact statevector -calculation based on the [`qiskit.quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) class. However, this can be -modified to include shot noise if the number of `shots` is set. -For reproducibility purposes, a `seed` will also be set in the following examples. - -There are two main ways of setting options in the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler): - -- Set keyword arguments in the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. -- Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. - -### Set keyword arguments for [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) - -If you only want to change the settings for a specific run, it can be more convenient to -set the options inside the [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run) method. You can do this by -passing them as keyword arguments. - -```python -job = sampler.run(qc, shots=2048, seed=123) -result = job.result() -print(result) -``` - -```python -SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) -``` - -### Modify [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options - -If you want to keep some configuration values for several runs, it can be better to -change the [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) options. That way you can use the same -[`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) object as many times as you wish without having to -rewrite the configuration values every time you use [`qiskit.primitives.Sampler.run`](../api/qiskit/qiskit.primitives.Sampler#run). - -#### Modify existing [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) - -If you prefer to change the options of an already-defined [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler), you can use -[`qiskit.primitives.Sampler.set_options`](../api/qiskit/qiskit.primitives.Sampler#set_options) and introduce the new options as keyword arguments. - -```python -sampler.set_options(shots=2048, seed=123) - -job = sampler.run(qc) -result = job.result() -print(result) -``` - -```python -SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}]) -``` - -#### Define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with the options - -If you prefer to define a new [`qiskit.primitives.Sampler`](../api/qiskit/qiskit.primitives.Sampler) with new options, you need to -define a `dict` like this one: - -```python -options = {"shots": 2048, "seed": 123} -``` - -And then you can 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}]) -```