Skip to content

Commit

Permalink
Add release notes for V2 of the primitives (#11589) (#11814)
Browse files Browse the repository at this point in the history
* Add release notes for V2 of the primitives

* Update releasenotes/notes/primitives-v2-df871c0c6ac0b94a.yaml

Co-authored-by: Christopher J. Wood <cjwood@us.ibm.com>

* Add separate release notes for the statevector estimators.

* update base class reno

* fix typo

* Copy example into StaevectorSampler

* Move all renos into one file, as suggested by @mtreinish

* Removed references to privatized classes

* typo

* Modify statevector sampler docs to not talk about SamplerPub

* remove more references to BindingsArray and ObservablesArray

and add Estimator example

* lint

* Apply suggestions from code review

Co-authored-by: Christopher J. Wood <cjwood@us.ibm.com>

* minor fixes from CR

* switch to pub variables instead of inline

* switch to quantum_info types in examples

* remove references to removed BasisObservable type

* do a bit of reorganization and write a migration section

* make the statevectorestimator do the plot in docs

* Apply suggestions from code review

Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

* remove comma

* address various minor code suggestions

* switch to get_bitstrings()

* revert accidental removal of V1 sections

* Fix Sphinx module-path imports

* Fix minor syntax errors

* Fix whitespace

* Stop importing docs with automodule

* add raw string directive

* add PrimitiveJob to the public API

* make some of Chris' changes

* rewrap textblocks to < 80 chars

---------

Co-authored-by: Christopher J. Wood <cjwood@us.ibm.com>
Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
(cherry picked from commit 172fa04)

Co-authored-by: Ian Hincks <ian.hincks@ibm.com>
  • Loading branch information
mergify[bot] and ihincks committed Feb 15, 2024
1 parent b73d77d commit b86d60b
Show file tree
Hide file tree
Showing 8 changed files with 856 additions and 298 deletions.
437 changes: 410 additions & 27 deletions qiskit/primitives/__init__.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions qiskit/primitives/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
Abstract base classes for primitives module.
"""

from .base_sampler import BaseSampler, BaseSamplerV2
from .base_estimator import BaseEstimator, BaseEstimatorV2
from .base_sampler import BaseSampler, BaseSamplerV1, BaseSamplerV2
from .base_estimator import BaseEstimator, BaseEstimatorV1, BaseEstimatorV2
from .estimator_result import EstimatorResult
from .sampler_result import SamplerResult
199 changes: 60 additions & 139 deletions qiskit/primitives/base/base_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,143 +10,7 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

r"""
.. estimator-desc:
========================
Overview of EstimatorV2
========================
:class:`~BaseEstimatorV2` is a primitive that estimates expectation values for provided quantum
circuit and observable combinations.
Following construction, an estimator is used by calling its :meth:`~.BaseEstimatorV2.run` method
with a list of pubs (Primitive Unified Blocs). Each pub contains three values that, together,
define a computation unit of work for the estimator to complete:
* a single :class:`~qiskit.circuit.QuantumCircuit`, possibly parametrized, whose final state we
define as :math:`\psi(\theta)`,
* one or more observables (specified as any :class:`~.ObservablesArrayLike`, including
:class:`~.Pauli`, :class:`~.SparsePauliOp`, ``str``) that specify which expectation values to
estimate, denoted :math:`H_j`, and
* a collection parameter value sets to bind the circuit against, :math:`\theta_k`.
Running an estimator returns a :class:`~qiskit.providers.JobV1` object, where calling
the method :meth:`qiskit.providers.JobV1.result` results in expectation value estimates and metadata
for each pub:
.. math::
\langle\psi(\theta_k)|H_j|\psi(\theta_k)\rangle
The observables and parameter values portion of a pub can be array-valued with arbitrary dimensions,
where standard broadcasting rules are applied, so that, in turn, the estimated result for each pub
is in general array-valued as well. For more information, please check
`here <https://github.com/Qiskit/RFCs/blob/master/0015-estimator-interface.md#arrays-and
-broadcasting->`_.
Here is an example of how the estimator is used.
.. code-block:: python
from qiskit.primitives.statevector_estimator import Estimator
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
psi1 = RealAmplitudes(num_qubits=2, reps=2)
psi2 = RealAmplitudes(num_qubits=2, reps=3)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
H2 = SparsePauliOp.from_list([("IZ", 1)])
H3 = SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)])
theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 1, 2, 3, 5, 8, 13]
theta3 = [1, 2, 3, 4, 5, 6]
estimator = Estimator()
# calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
job = estimator.run([(psi1, hamiltonian1, [theta1])])
job_result = job.result() # It will block until the job finishes.
print(f"The primitive-job finished with result {job_result}"))
# calculate [ [<psi1(theta1)|H1|psi1(theta1)>,
# <psi1(theta3)|H3|psi1(theta3)>],
# [<psi2(theta2)|H2|psi2(theta2)>] ]
job2 = estimator.run(
[(psi1, [hamiltonian1, hamiltonian3], [theta1, theta3]), (psi2, hamiltonian2, theta2)]
)
job_result = job2.result()
print(f"The primitive-job finished with result {job_result}")
========================
Overview of EstimatorV1
========================
Estimator class estimates expectation values of quantum circuits and observables.
An estimator is initialized with an empty parameter set. The estimator is used to
create a :class:`~qiskit.providers.JobV1`, via the
:meth:`qiskit.primitives.Estimator.run()` method. This method is called
with the following parameters
* quantum circuits (:math:`\psi_i(\theta)`): list of (parameterized) quantum circuits
(a list of :class:`~qiskit.circuit.QuantumCircuit` objects).
* observables (:math:`H_j`): a list of :class:`~qiskit.quantum_info.SparsePauliOp`
objects.
* parameter values (:math:`\theta_k`): list of sets of values
to be bound to the parameters of the quantum circuits
(list of list of float).
The method returns a :class:`~qiskit.providers.JobV1` object, calling
:meth:`qiskit.providers.JobV1.result()` yields the
a list of expectation values plus optional metadata like confidence intervals for
the estimation.
.. math::
\langle\psi_i(\theta_k)|H_j|\psi_i(\theta_k)\rangle
Here is an example of how the estimator is used.
.. code-block:: python
from qiskit.primitives import Estimator
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
psi1 = RealAmplitudes(num_qubits=2, reps=2)
psi2 = RealAmplitudes(num_qubits=2, reps=3)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
H2 = SparsePauliOp.from_list([("IZ", 1)])
H3 = SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)])
theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 1, 2, 3, 5, 8, 13]
theta3 = [1, 2, 3, 4, 5, 6]
estimator = Estimator()
# calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
job = estimator.run([psi1], [H1], [theta1])
job_result = job.result() # It will block until the job finishes.
print(f"The primitive-job finished with result {job_result}"))
# calculate [ <psi1(theta1)|H1|psi1(theta1)>,
# <psi2(theta2)|H2|psi2(theta2)>,
# <psi1(theta3)|H3|psi1(theta3)> ]
job2 = estimator.run([psi1, psi2, psi1], [H1, H2, H3], [theta1, theta2, theta3])
job_result = job2.result()
print(f"The primitive-job finished with result {job_result}")
"""
r"""Base Estimator Classes"""

from __future__ import annotations

Expand Down Expand Up @@ -178,9 +42,66 @@


class BaseEstimatorV1(BasePrimitive, Generic[T]):
"""Estimator base class.
r"""Estimator V1 base class.
Base class for Estimator that estimates expectation values of quantum circuits and observables.
An estimator is initialized with an empty parameter set. The estimator is used to
create a :class:`~qiskit.providers.JobV1`, via the
:meth:`qiskit.primitives.Estimator.run()` method. This method is called
with the following parameters
* quantum circuits (:math:`\psi_i(\theta)`): list of (parameterized) quantum circuits
(a list of :class:`~qiskit.circuit.QuantumCircuit` objects).
* observables (:math:`H_j`): a list of :class:`~qiskit.quantum_info.SparsePauliOp`
objects.
* parameter values (:math:`\theta_k`): list of sets of values
to be bound to the parameters of the quantum circuits
(list of list of float).
The method returns a :class:`~qiskit.providers.JobV1` object, calling
:meth:`qiskit.providers.JobV1.result()` yields the
a list of expectation values plus optional metadata like confidence intervals for
the estimation.
.. math::
\langle\psi_i(\theta_k)|H_j|\psi_i(\theta_k)\rangle
Here is an example of how the estimator is used.
.. code-block:: python
from qiskit.primitives import Estimator
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
psi1 = RealAmplitudes(num_qubits=2, reps=2)
psi2 = RealAmplitudes(num_qubits=2, reps=3)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
H2 = SparsePauliOp.from_list([("IZ", 1)])
H3 = SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)])
theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 1, 2, 3, 5, 8, 13]
theta3 = [1, 2, 3, 4, 5, 6]
estimator = Estimator()
# calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
job = estimator.run([psi1], [H1], [theta1])
job_result = job.result() # It will block until the job finishes.
print(f"The primitive-job finished with result {job_result}"))
# calculate [ <psi1(theta1)|H1|psi1(theta1)>,
# <psi2(theta2)|H2|psi2(theta2)>,
# <psi1(theta3)|H3|psi1(theta3)> ]
job2 = estimator.run([psi1, psi2, psi1], [H1, H2, H3], [theta1, theta2, theta3])
job_result = job2.result()
print(f"The primitive-job finished with result {job_result}")
"""

__hash__ = None
Expand Down Expand Up @@ -273,7 +194,7 @@ def _run(


class BaseEstimatorV2(ABC):
"""Estimator base class version 2.
r"""Estimator V2 base class.
An estimator estimates expectation values for provided quantum circuit and
observable combinations.
Expand Down
Loading

0 comments on commit b86d60b

Please sign in to comment.