Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VQE implementation with estimator primitive #8702

Merged
merged 101 commits into from
Sep 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
0a35c1a
Add minimally working VQE with estimator primitive implementation.
declanmillar Aug 31, 2022
ac88412
Revert from dataclass results to original result classes.
declanmillar Sep 1, 2022
3fd8f3c
Enforce positional and keyword VQE arguments.
declanmillar Sep 2, 2022
9b987cc
Move aux op eval logic to function
declanmillar Sep 2, 2022
378aac8
Update docstring.
declanmillar Sep 2, 2022
629e6de
Remove max_evals_grouped. Force to set directly on optimizer.
declanmillar Sep 5, 2022
499c35e
Remove validate min import.
declanmillar Sep 5, 2022
689e2c8
Make note that eval_observables will be used to eval aux ops.
declanmillar Sep 5, 2022
1a43460
Add initial vqe tests.
declanmillar Sep 5, 2022
8d6bd1c
Have VQE inherit from VariationalAlgorithm.
declanmillar Sep 5, 2022
f1ffb54
Move energy evaluation to unnested function.
declanmillar Sep 5, 2022
fcb2846
Construct h2_op using SparsePauliOp
declanmillar Sep 5, 2022
903614c
Add gradient with primitives support.
declanmillar Sep 6, 2022
27d02b0
Update docstrings
declanmillar Sep 6, 2022
813a344
update broadcast handling
declanmillar Sep 7, 2022
70ba38b
update eval_energy output for batching
declanmillar Sep 7, 2022
36dfd3b
add incomplete QNSPA test
declanmillar Sep 7, 2022
3c79faa
fix batch evaluation of QNSPSA test
declanmillar Sep 7, 2022
4695cc3
remove vqe callback
declanmillar Sep 7, 2022
105c5db
move estimator to first arg
declanmillar Sep 7, 2022
9131190
remove usused imports
declanmillar Sep 7, 2022
c726397
add minimum eigensolvers test init file
declanmillar Sep 7, 2022
cfdea10
add aux ops tests and prepare for new eval_operators
declanmillar Sep 8, 2022
68788ca
no longer support account for Nones in aux_ops
declanmillar Sep 9, 2022
7ab77e4
correct typing for MinimumEigensolver
declanmillar Sep 9, 2022
632b3aa
Compute default initial point using ansatz bounds.
declanmillar Sep 12, 2022
6aa5373
Add NumPyMinimumEigensolverResult
declanmillar Sep 12, 2022
a002467
Fix type hints
declanmillar Sep 12, 2022
c83c7b9
Fix type hints
declanmillar Sep 12, 2022
98648f0
Formatting
declanmillar Sep 12, 2022
2ed3ff3
Do not store NumPyMES result inside the algo.
declanmillar Sep 12, 2022
aced280
Provide default values for ansatz and estimator
declanmillar Sep 12, 2022
9459603
Formatting
declanmillar Sep 12, 2022
3623ad7
fix old and new batching
declanmillar Sep 12, 2022
93213dc
Add tests for NumpyMES and import in module.
declanmillar Sep 12, 2022
5defcd5
Use lazy formatting in log messages
declanmillar Sep 12, 2022
b7c4a74
Use lazy formatting in log messages
declanmillar Sep 12, 2022
af47dea
Add back callback to VQE.
declanmillar Sep 13, 2022
f682616
minor renaming
declanmillar Sep 13, 2022
16dc12c
raise algorithm error if primitive jobs fail
declanmillar Sep 13, 2022
994247b
Add return documentation
declanmillar Sep 13, 2022
688f9f1
Improve var names and docstrings.
declanmillar Sep 14, 2022
a9d6d41
Apply suggestions from code review
declanmillar Sep 15, 2022
6e99b34
minor formatting
declanmillar Sep 15, 2022
6abff88
minor formatting
declanmillar Sep 15, 2022
0b5c185
Ensure evaluate_energy/gradient match
declanmillar Sep 15, 2022
e2dafa8
return bounds logic; fix some docstrings and minor refactor
declanmillar Sep 16, 2022
1eb2329
Force keyword arguments in vqe.
declanmillar Sep 16, 2022
c05cdbc
Use estimate_observables function
declanmillar Sep 16, 2022
4cbbe67
break up numpy mes tests with subTest
declanmillar Sep 20, 2022
455981c
formatting
declanmillar Sep 20, 2022
ae66409
remove redundant eval_aux_ops
declanmillar Sep 20, 2022
3c17862
add typehints to docstring attributes
declanmillar Sep 20, 2022
067cd07
remove usused imports
declanmillar Sep 20, 2022
3acf449
remove default ansatz
declanmillar Sep 20, 2022
b3db998
remove usused imports
declanmillar Sep 20, 2022
1990045
update typehints
declanmillar Sep 20, 2022
86e7b86
avoid changing the original ansatz
declanmillar Sep 21, 2022
bd0c97d
avoid changing the original ansatz
declanmillar Sep 21, 2022
7cdd399
create separate function to build vqe result
declanmillar Sep 21, 2022
c204a7e
Correct aux operator eignvalue type hint
declanmillar Sep 21, 2022
91fe427
add variance to callback
declanmillar Sep 22, 2022
7afa7eb
use std_dev in callback rather than variance
declanmillar Sep 23, 2022
ac2871a
formatting
declanmillar Sep 23, 2022
0e0a5d4
return variance and shots in callback
declanmillar Sep 23, 2022
8d238bf
return full metadata in callback
declanmillar Sep 23, 2022
a2cd35a
Move validation functions to algorithms/utils
declanmillar Sep 23, 2022
4dab8bc
correct the callback attribute documentation
declanmillar Sep 23, 2022
78d21c5
correct the callback attribute typehint docstring
declanmillar Sep 23, 2022
d9f5cb2
update VQE docstring
declanmillar Sep 23, 2022
eaea3e6
release note and pending-depreciate old algs
declanmillar Sep 23, 2022
183c20c
update vqe class docstring
declanmillar Sep 23, 2022
d01d47b
Apply suggestions from code review
declanmillar Sep 26, 2022
f06a74c
Do not copy ansatz
declanmillar Sep 26, 2022
9cfb1b2
Note pending depreciation of old algs
declanmillar Sep 26, 2022
3ec9dba
fix docstrings and imports
declanmillar Sep 26, 2022
4d7a0fd
Fix issues with building docs
declanmillar Sep 26, 2022
4a16903
Include OptimizerResult in VQEResult
declanmillar Sep 26, 2022
6a15540
Remove trailing whitespace
declanmillar Sep 26, 2022
4fdf4f5
Fix math notation in docstring
declanmillar Sep 26, 2022
355d887
estimate_obervables to return metadata @ElePT +VQE
declanmillar Sep 26, 2022
b0b8f37
add example in release note
declanmillar Sep 26, 2022
c144688
Update evaluate_observables docstring
declanmillar Sep 26, 2022
8fed152
Fix observables_evaluator tests.
declanmillar Sep 26, 2022
682d3cb
fix trotter_qrte tests and remove depreciation
declanmillar Sep 26, 2022
2976ac9
formatting
declanmillar Sep 26, 2022
998121f
remove unused import
declanmillar Sep 26, 2022
8aeed79
Apply suggestions to docstring from code review
declanmillar Sep 26, 2022
483fbd2
Update VQE docstring
declanmillar Sep 26, 2022
7e2ee3d
Remove printing
declanmillar Sep 26, 2022
31219bf
Add parameters to estimate observables
ElePT Sep 26, 2022
511caca
Fix estimate obs. unit test
ElePT Sep 26, 2022
34246d3
Update arg description
declanmillar Sep 26, 2022
12f6426
Update arg description
declanmillar Sep 26, 2022
efc0565
keep equation part of sentence
declanmillar Sep 26, 2022
b1c55ca
dict -> dict[str, Any]
declanmillar Sep 26, 2022
50eba6d
Merge branch 'main' into vqe-with-estimator-primitive
woodsp-ibm Sep 27, 2022
18b5b63
Update qiskit/algorithms/optimizers/spsa.py
ElePT Sep 27, 2022
0e0ebac
introduce FilterType and aux_operator_eigenvalues -> aux_operators_ev…
declanmillar Sep 27, 2022
3357ebe
Correct typehint
declanmillar Sep 27, 2022
66ba346
update vqe docstring and use old typing for type alias
declanmillar Sep 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions qiskit/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,12 @@
linear_solvers


Minimum Eigensolvers
--------------------
Minimum Eigen Solvers
declanmillar marked this conversation as resolved.
Show resolved Hide resolved
---------------------

Algorithms that can find the minimum eigenvalue of an operator.
These algorithms are pending depreciation. One should instead make use of the
Minimum Eigensolver classes in the section below, which leverage Runtime primitives.

.. autosummary::
:toctree: ../stubs/
Expand All @@ -203,6 +205,16 @@
QAOA
VQE

Minimum Eigensolvers
--------------------

Algorithms that can find the minimum eigenvalue of an operator and leverage primitives.

.. autosummary::
:toctree: ../stubs/

minimum_eigensolvers
declanmillar marked this conversation as resolved.
Show resolved Hide resolved


Optimizers
----------
Expand Down
48 changes: 48 additions & 0 deletions qiskit/algorithms/minimum_eigensolvers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
============================================================================
Minimum Eigensolvers Package (:mod:`qiskit.algorithms.minimum_eigensolvers`)
============================================================================

.. currentmodule:: qiskit.algorithms.minimum_eigensolvers

Minimum Eigensolvers
====================
.. autosummary::
:toctree: ../stubs/

MinimumEigensolver
NumPyMinimumEigensolver
VQE

.. autosummary::
:toctree: ../stubs/

MinimumEigensolverResult
NumPyMinimumEigensolverResult
VQEResult
"""

from .minimum_eigensolver import MinimumEigensolver, MinimumEigensolverResult
from .numpy_minimum_eigensolver import NumPyMinimumEigensolver, NumPyMinimumEigensolverResult
from .vqe import VQE, VQEResult

declanmillar marked this conversation as resolved.
Show resolved Hide resolved
__all__ = [
"MinimumEigensolver",
"MinimumEigensolverResult",
"NumPyMinimumEigensolver",
"NumPyMinimumEigensolverResult",
"VQE",
"VQEResult",
]
99 changes: 99 additions & 0 deletions qiskit/algorithms/minimum_eigensolvers/minimum_eigensolver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""The minimum eigensolver interface and result."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any

from qiskit.opflow import PauliSumOp
from qiskit.quantum_info.operators.base_operator import BaseOperator

from ..algorithm_result import AlgorithmResult
from ..list_or_dict import ListOrDict


class MinimumEigensolver(ABC):
"""The minimum eigensolver interface.

Algorithms that can compute a minimum eigenvalue for an operator may implement this interface to
allow different algorithms to be used interchangeably.
"""

@abstractmethod
def compute_minimum_eigenvalue(
self,
operator: BaseOperator | PauliSumOp,
aux_operators: ListOrDict[BaseOperator | PauliSumOp] | None = None,
) -> "MinimumEigensolverResult":
"""
Computes the minimum eigenvalue. The ``operator`` and ``aux_operators`` can be supplied here
and if not ``None`` will override any already set into algorithm so it can be reused with
different operators. While an ``operator`` is required by algorithms, ``aux_operators`` are
optional.

Args:
operator: Qubit operator of the observable.
aux_operators: Optional list of auxiliary operators to be evaluated with the
parameters of the minimum eigenvalue main result and their expectation values
returned. For instance in chemistry these can be dipole operators and total particle
count operators, so we can get values for these at the ground state.

Returns:
A minimum eigensolver result.
"""
return MinimumEigensolverResult()

@classmethod
def supports_aux_operators(cls) -> bool:
"""Whether computing the expectation value of auxiliary operators is supported.

If the minimum eigensolver computes an eigenvalue of the main ``operator`` then it can
compute the expectation value of the ``aux_operators`` for that state. Otherwise they will
be ignored.

Returns:
True if aux_operator expectations can be evaluated, False otherwise
"""
return False


class MinimumEigensolverResult(AlgorithmResult):
"""Minimum eigensolver result."""

def __init__(self) -> None:
super().__init__()
self._eigenvalue = None
self._aux_operators_evaluated = None

@property
def eigenvalue(self) -> complex | None:
"""The computed minimum eigenvalue."""
return self._eigenvalue

@eigenvalue.setter
def eigenvalue(self, value: complex) -> None:
self._eigenvalue = value
declanmillar marked this conversation as resolved.
Show resolved Hide resolved

@property
def aux_operators_evaluated(self) -> ListOrDict[tuple[complex, dict[str, Any]]] | None:
"""The aux operator expectation values.

These values are in fact tuples formatted as (mean, (variance, shots)).
"""
return self._aux_operators_evaluated

@aux_operators_evaluated.setter
def aux_operators_evaluated(self, value: ListOrDict[tuple[complex, dict[str, Any]]]) -> None:
self._aux_operators_evaluated = value
106 changes: 106 additions & 0 deletions qiskit/algorithms/minimum_eigensolvers/numpy_minimum_eigensolver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""The NumPy minimum eigensolver algorithm and result."""

from __future__ import annotations

from typing import Callable, List, Union, Optional
import logging
import numpy as np

from qiskit.opflow import PauliSumOp
from qiskit.quantum_info.operators.base_operator import BaseOperator

# TODO this path will need updating when VQD is merged
from ..eigen_solvers.numpy_eigen_solver import NumPyEigensolver
declanmillar marked this conversation as resolved.
Show resolved Hide resolved
from .minimum_eigensolver import MinimumEigensolver, MinimumEigensolverResult
from ..list_or_dict import ListOrDict

logger = logging.getLogger(__name__)

# future type annotations not supported in type aliases in 3.8
FilterType = Callable[[Union[List, np.ndarray], float, Optional[ListOrDict[float]]], bool]


class NumPyMinimumEigensolver(MinimumEigensolver):
"""
The NumPy minimum eigensolver algorithm.
"""

def __init__(
self,
filter_criterion: FilterType | None = None,
) -> None:
"""
Args:
filter_criterion: callable that allows to filter eigenvalues/eigenstates. The minimum
eigensolver is only searching over feasible states and returns an eigenstate that
has the smallest eigenvalue among feasible states. The callable has the signature
``filter(eigenstate, eigenvalue, aux_values)`` and must return a boolean to indicate
whether to consider this value or not. If there is no feasible element, the result
can even be empty.
"""
self._eigensolver = NumPyEigensolver(filter_criterion=filter_criterion)

@property
def filter_criterion(
self,
) -> FilterType | None:
"""Returns the criterion for filtering eigenstates/eigenvalues."""
return self._eigensolver.filter_criterion

@filter_criterion.setter
def filter_criterion(
self,
filter_criterion: FilterType,
) -> None:
self._eigensolver.filter_criterion = filter_criterion

@classmethod
def supports_aux_operators(cls) -> bool:
return NumPyEigensolver.supports_aux_operators()

def compute_minimum_eigenvalue(
self,
operator: BaseOperator | PauliSumOp,
aux_operators: ListOrDict[BaseOperator | PauliSumOp] | None = None,
) -> NumPyMinimumEigensolverResult:
super().compute_minimum_eigenvalue(operator, aux_operators)
eigensolver_result = self._eigensolver.compute_eigenvalues(operator, aux_operators)
result = NumPyMinimumEigensolverResult()
if eigensolver_result.eigenvalues is not None and len(eigensolver_result.eigenvalues) > 0:
result.eigenvalue = eigensolver_result.eigenvalues[0]
result.eigenstate = eigensolver_result.eigenstates[0]
if eigensolver_result.aux_operator_eigenvalues:
result.aux_operators_evaluated = eigensolver_result.aux_operator_eigenvalues[0]

logger.debug("NumPy minimum eigensolver result: %s", result)

return result


class NumPyMinimumEigensolverResult(MinimumEigensolverResult):
"""NumPy minimum eigensolver result."""

def __init__(self) -> None:
super().__init__()
self._eigenstate = None

@property
def eigenstate(self) -> np.ndarray | None:
"""Returns the eigenstate corresponding to the computed minimum eigenvalue."""
return self._eigenstate

@eigenstate.setter
def eigenstate(self, value: np.ndarray) -> None:
declanmillar marked this conversation as resolved.
Show resolved Hide resolved
self._eigenstate = value
Loading