Skip to content

Commit 9722edb

Browse files
Guillermo-Mijares-Vilarinowoodsp-ibmHuangJunyeElePT1ucian0
authored
Add how-to guides about primitives (Qiskit/qiskit#9716)
* Added how-to section * added how to compose circuits guide * added how to visualize circuit guide * add how to create parameterized circuit guide * add guides * removed latex circuit visualization * fixed title underlines * Fix typo * explicitly set cregbundle to False when appending circuit with classical register * Fix typo * Added explanation about needed latex distribution * added link to qiskit.visualization module * Simplified references * Change 'we' to 'you' * Changed how_to.rst to how_to/index.rst * Removed jupyter-execute from create_a_quantum_circuit * Removed jupyter-execute from create_a_parameterized_circuit * Removed jupyter-execute from compose_quantum_circuits * Removed jupyter-execute from visualize_a_quantum_circuit * Add sphinx.ext.doctest to conf.py * Change header symbol for index and visualization guide * Added guides for sampler and estimator and simplified toctree * Fixed underline * Add links to how-to create circuit * Added section about parameterized circuits to primitives how-tos * Remove other how-tos * Remove links * Added reference to other implementations of primitives * Update docs/how_to/use_estimator.rst Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com> * Improved titles * set global doctest flags and disable automatic doctests * Added part about changing options * Add new aer docs page to intersphinx * Added notes about circuit measurements * Improved notes about circuit measurements * Update docs/how_to/use_estimator.rst Co-authored-by: Junye Huang <h.jun.ye@gmail.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Junye Huang <h.jun.ye@gmail.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Junye Huang <h.jun.ye@gmail.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Junye Huang <h.jun.ye@gmail.com> * Added numpy to intersphinx and note about doctest and plot directive * Added note about quasi-probabilities * rename how to to How-to Guides * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Update docs/how_to/use_sampler.rst Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * Remove generally * Changed sampler initial note to mention BackendSampler * Update docs/how_to/use_sampler.rst Co-authored-by: Luciano Bello <bel@zurich.ibm.com> * Added code example for backend primitives and link to providers page * Update intersphinx mapping to ecosystem for aer and runtime * Change rustworkx link * Add "primitive" to estimator how-to title Co-authored-by: Luciano Bello <bel@zurich.ibm.com> * Change hypothetical import to avoid confusion Co-authored-by: Luciano Bello <bel@zurich.ibm.com> * Update docs/how_to/use_estimator.rst Co-authored-by: Luciano Bello <bel@zurich.ibm.com> * Include "primitive" word in sampler how-to title Co-authored-by: Luciano Bello <bel@zurich.ibm.com> * Improve phrasing Co-authored-by: Luciano Bello <bel@zurich.ibm.com> * Include notice about doctest and plot directive incompatibility in sampler guide * change->modify sampler options * change qiskit_provider to <some_qiskit_provider> * shots->amount of shots in estimator how-to * Add quick explanation about using multiple circuits and observables and adjust plurals * singular * singular --------- Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com> Co-authored-by: Junye Huang <h.jun.ye@gmail.com> Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
1 parent 4210ca5 commit 9722edb

1 file changed

Lines changed: 255 additions & 0 deletions

File tree

qiskit-docs/how_to/use_sampler.rst

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
###############################################################
2+
Compute circuit output probabilities with ``Sampler`` primitive
3+
###############################################################
4+
5+
This guide shows how to get the probability distribution of a quantum circuit with the :class:`~qiskit.primitives.Sampler` primitive.
6+
7+
.. note::
8+
9+
While this guide uses Qiskit’s reference implementation, the ``Sampler`` primitive can be run with any provider using :class:`~qiskit.primitives.BackendSampler`.
10+
11+
.. code-block::
12+
13+
from qiskit.primitives import BackendSampler
14+
from <some_qiskit_provider> import QiskitProvider
15+
16+
provider = QiskitProvider()
17+
backend = provider.get_backend('backend_name')
18+
sampler = BackendSampler(backend)
19+
20+
There are some providers that implement primitives natively (see `this page <http://qiskit.org/providers/#primitives>`_ for more details).
21+
22+
Initialize quantum circuits
23+
===========================
24+
25+
The first step is to create the :class:`~qiskit.circuit.QuantumCircuit`\ s from which you want to obtain the probability distribution.
26+
27+
.. plot::
28+
:include-source:
29+
30+
from qiskit import QuantumCircuit
31+
32+
qc = QuantumCircuit(2)
33+
qc.h(0)
34+
qc.cx(0,1)
35+
qc.measure_all()
36+
qc.draw("mpl")
37+
38+
.. testsetup::
39+
40+
# This code is repeated (but hidden) because we will need to use the variables with the extension sphinx.ext.doctest (testsetup/testcode/testoutput directives)
41+
# and we can't reuse the variables from the plot directive above because they are incompatible.
42+
# The plot directive is used to draw the circuit with matplotlib and the code is shown because of the include-source flag.
43+
44+
from qiskit import QuantumCircuit
45+
46+
qc = QuantumCircuit(2)
47+
qc.h(0)
48+
qc.cx(0,1)
49+
qc.measure_all()
50+
51+
.. note::
52+
53+
The :class:`~qiskit.circuit.QuantumCircuit` you pass to :class:`~qiskit.primitives.Sampler` has to include measurements.
54+
55+
Initialize the ``Sampler``
56+
==========================
57+
58+
Then, you need to create a :class:`~qiskit.primitives.Sampler` instance.
59+
60+
.. testcode::
61+
62+
from qiskit.primitives import Sampler
63+
64+
sampler = Sampler()
65+
66+
Run and get results
67+
===================
68+
69+
Now that you have defined your ``sampler``, you can run it by calling the :meth:`~qiskit.primitives.Sampler.run` method,
70+
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)
71+
with the :meth:`~qiskit.providers.JobV1.result` method.
72+
73+
.. testcode::
74+
75+
job = sampler.run(qc)
76+
result = job.result()
77+
print(result)
78+
79+
.. testoutput::
80+
81+
SamplerResult(quasi_dists=[{0: 0.4999999999999999, 3: 0.4999999999999999}], metadata=[{}])
82+
83+
While this example only uses one :class:`~qiskit.circuit.QuantumCircuit`, if you want to sample multiple circuits you can
84+
pass a ``list`` of :class:`~qiskit.circuit.QuantumCircuit` instances to the :meth:`~qiskit.primitives.Sampler.run` method.
85+
86+
Get the probability distribution
87+
--------------------------------
88+
89+
From these results you can extract the quasi-probability distributions with the attribute :attr:`~qiskit.primitives.SamplerResult.quasi_dists`.
90+
91+
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.
92+
``result.quasi_dists[i]`` is the quasi-probability distribution of the ``i``-th circuit.
93+
94+
.. note::
95+
96+
A quasi-probability distribution differs from a probability distribution in that negative values are also allowed.
97+
However the quasi-probabilities must sum up to 1 like probabilities.
98+
Negative quasi-probabilities may appear when using error mitigation techniques.
99+
100+
.. testcode::
101+
102+
quasi_dist = result.quasi_dists[0]
103+
print(quasi_dist)
104+
105+
.. testoutput::
106+
107+
{0: 0.4999999999999999, 3: 0.4999999999999999}
108+
109+
Probability distribution with binary outputs
110+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111+
112+
If you prefer to see the output keys as binary strings instead of decimal numbers, you can use the
113+
:meth:`~qiskit.result.QuasiDistribution.binary_probabilities` method.
114+
115+
.. testcode::
116+
117+
print(quasi_dist.binary_probabilities())
118+
119+
.. testoutput::
120+
121+
{'00': 0.4999999999999999, '11': 0.4999999999999999}
122+
123+
Parameterized circuit with ``Sampler``
124+
========================================
125+
126+
The :class:`~qiskit.primitives.Sampler` primitive can be run with unbound parameterized circuits like the one below.
127+
You can also manually bind values to the parameters of the circuit and follow the steps
128+
of the previous example.
129+
130+
.. testcode::
131+
132+
from qiskit.circuit import Parameter
133+
134+
theta = Parameter('θ')
135+
param_qc = QuantumCircuit(2)
136+
param_qc.ry(theta, 0)
137+
param_qc.cx(0,1)
138+
param_qc.measure_all()
139+
print(param_qc.draw())
140+
141+
.. testoutput::
142+
143+
┌───────┐ ░ ┌─┐
144+
q_0: ┤ Ry(θ) ├──■───░─┤M├───
145+
└───────┘┌─┴─┐ ░ └╥┘┌─┐
146+
q_1: ─────────┤ X ├─░──╫─┤M├
147+
└───┘ ░ ║ └╥┘
148+
meas: 2/══════════════════╩══╩═
149+
0 1
150+
151+
The main difference from the previous case is that now you need to specify the sets of parameter values
152+
for which you want to evaluate the expectation value as a ``list`` of ``list``\ s of ``float``\ s.
153+
The ``i``-th element of the outer ``list`` is the set of parameter values
154+
that corresponds to the ``i``-th circuit.
155+
156+
.. testcode::
157+
158+
import numpy as np
159+
160+
parameter_values = [[0], [np.pi/6], [np.pi/2]]
161+
162+
job = sampler.run([param_qc]*3, parameter_values=parameter_values)
163+
dists = job.result().quasi_dists
164+
165+
for i in range(3):
166+
print(f"Parameter: {parameter_values[i][0]:.5f}\t Probabilities: {dists[i]}")
167+
168+
.. testoutput::
169+
170+
Parameter: 0.00000 Probabilities: {0: 1.0}
171+
Parameter: 0.52360 Probabilities: {0: 0.9330127018922194, 3: 0.0669872981077807}
172+
Parameter: 1.57080 Probabilities: {0: 0.5000000000000001, 3: 0.4999999999999999}
173+
174+
Change run options
175+
==================
176+
177+
Your workflow might require tuning primitive run options, such as the amount of shots.
178+
179+
By default, the reference :class:`~qiskit.primitives.Sampler` class performs an exact statevector
180+
calculation based on the :class:`~qiskit.quantum_info.Statevector` class. However, this can be
181+
modified to include shot noise if the number of ``shots`` is set.
182+
For reproducibility purposes, a ``seed`` will also be set in the following examples.
183+
184+
There are two main ways of setting options in the :class:`~qiskit.primitives.Sampler`:
185+
186+
* Set keyword arguments in the :meth:`~qiskit.primitives.Sampler.run` method.
187+
* Modify :class:`~qiskit.primitives.Sampler` options.
188+
189+
Set keyword arguments for :meth:`~qiskit.primitives.Sampler.run`
190+
----------------------------------------------------------------
191+
192+
If you only want to change the settings for a specific run, it can be more convenient to
193+
set the options inside the :meth:`~qiskit.primitives.Sampler.run` method. You can do this by
194+
passing them as keyword arguments.
195+
196+
.. testcode::
197+
198+
job = sampler.run(qc, shots=2048, seed=123)
199+
result = job.result()
200+
print(result)
201+
202+
.. testoutput::
203+
204+
SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])
205+
206+
Modify :class:`~qiskit.primitives.Sampler` options
207+
---------------------------------------------------
208+
209+
If you want to keep some configuration values for several runs, it can be better to
210+
change the :class:`~qiskit.primitives.Sampler` options. That way you can use the same
211+
:class:`~qiskit.primitives.Sampler` object as many times as you wish without having to
212+
rewrite the configuration values every time you use :meth:`~qiskit.primitives.Sampler.run`.
213+
214+
Modify existing :class:`~qiskit.primitives.Sampler`
215+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
216+
217+
If you prefer to change the options of an already-defined :class:`~qiskit.primitives.Sampler`, you can use
218+
:meth:`~qiskit.primitives.Sampler.set_options` and introduce the new options as keyword arguments.
219+
220+
.. testcode::
221+
222+
sampler.set_options(shots=2048, seed=123)
223+
224+
job = sampler.run(qc)
225+
result = job.result()
226+
print(result)
227+
228+
.. testoutput::
229+
230+
SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])
231+
232+
Define a new :class:`~qiskit.primitives.Sampler` with the options
233+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
234+
235+
If you prefer to define a new :class:`~qiskit.primitives.Sampler` with new options, you need to
236+
define a ``dict`` like this one:
237+
238+
.. testcode::
239+
240+
options = {"shots": 2048, "seed": 123}
241+
242+
And then you can introduce it into your new :class:`~qiskit.primitives.Sampler` with the
243+
``options`` argument.
244+
245+
.. testcode::
246+
247+
sampler = Sampler(options=options)
248+
249+
job = sampler.run(qc)
250+
result = job.result()
251+
print(result)
252+
253+
.. testoutput::
254+
255+
SamplerResult(quasi_dists=[{0: 0.5205078125, 3: 0.4794921875}], metadata=[{'shots': 2048}])

0 commit comments

Comments
 (0)