-
Notifications
You must be signed in to change notification settings - Fork 2.9k
VQE implementation with estimator primitive #8702
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
Changes from 97 commits
0a35c1a
ac88412
3fd8f3c
9b987cc
378aac8
629e6de
499c35e
689e2c8
1a43460
8d6bd1c
f1ffb54
fcb2846
903614c
27d02b0
813a344
70ba38b
36dfd3b
3c79faa
4695cc3
105c5db
9131190
c726397
cfdea10
68788ca
7ab77e4
632b3aa
6aa5373
a002467
c83c7b9
98648f0
2ed3ff3
aced280
9459603
3623ad7
93213dc
5defcd5
b7c4a74
af47dea
f682616
16dc12c
994247b
688f9f1
a9d6d41
6e99b34
6abff88
0b5c185
e2dafa8
1eb2329
c05cdbc
4cbbe67
455981c
ae66409
3c17862
067cd07
3acf449
b3db998
1990045
86e7b86
bd0c97d
7cdd399
c204a7e
91fe427
7afa7eb
ac2871a
0e0a5d4
8d238bf
a2cd35a
4dab8bc
78d21c5
d9f5cb2
eaea3e6
183c20c
d01d47b
f06a74c
9cfb1b2
3ec9dba
4d7a0fd
4a16903
6a15540
4fdf4f5
355d887
b0b8f37
c144688
8fed152
682d3cb
2976ac9
998121f
8aeed79
483fbd2
7e2ee3d
31219bf
511caca
34246d3
12f6426
efc0565
b1c55ca
50eba6d
18b5b63
0e0ebac
3357ebe
66ba346
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
| """ | ||
|
|
||
|
declanmillar marked this conversation as resolved.
|
||
| from .minimum_eigensolver import MinimumEigensolver, MinimumEigensolverResult | ||
| from .numpy_minimum_eigensolver import NumPyMinimumEigensolver, NumPyMinimumEigensolverResult | ||
| from .vqe import VQE, VQEResult | ||
|
|
||
|
declanmillar marked this conversation as resolved.
|
||
| __all__ = [ | ||
| "MinimumEigensolver", | ||
| "MinimumEigensolverResult", | ||
| "NumPyMinimumEigensolver", | ||
| "NumPyMinimumEigensolverResult", | ||
| "VQE", | ||
| "VQEResult", | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| # 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 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_operator_eigenvalues = 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.
|
||
|
|
||
| @property | ||
| def aux_operator_eigenvalues(self) -> ListOrDict[tuple[complex, tuple[complex, int]]] | None: | ||
| """The aux operator expectation values. | ||
|
|
||
| These values are in fact tuples formatted as (mean, (variance, shots)). | ||
| """ | ||
| return self._aux_operator_eigenvalues | ||
|
|
||
| @aux_operator_eigenvalues.setter | ||
| def aux_operator_eigenvalues( | ||
| self, value: ListOrDict[tuple[complex, tuple[complex, int]]] | ||
| ) -> None: | ||
| self._aux_operator_eigenvalues = value | ||
|
declanmillar marked this conversation as resolved.
Outdated
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,105 @@ | ||||||
| # 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 | ||||||
| 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 | ||||||
| from ..eigen_solvers.numpy_eigen_solver import NumPyEigensolver | ||||||
|
declanmillar marked this conversation as resolved.
|
||||||
| from .minimum_eigensolver import MinimumEigensolver, MinimumEigensolverResult | ||||||
| from ..list_or_dict import ListOrDict | ||||||
|
|
||||||
| logger = logging.getLogger(__name__) | ||||||
|
|
||||||
|
|
||||||
| class NumPyMinimumEigensolver(MinimumEigensolver): | ||||||
| """ | ||||||
| The NumPy minimum eigensolver algorithm. | ||||||
| """ | ||||||
|
|
||||||
| def __init__( | ||||||
| self, | ||||||
| filter_criterion: Callable[ | ||||||
| [list | np.ndarray, float, ListOrDict[float] | None], bool | ||||||
| ] = None, | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure whether it requires
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The prior signature was
I imagine this is saying that the filter criteria is applied to the aux ops result which may be None. I would have thought the filter would not have needed to be called in this case but this is how it has been.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change made in the commit that addresses your comment below. |
||||||
| ) -> 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, | ||||||
| ) -> Callable[[list | np.ndarray, float, ListOrDict[float] | None], bool] | None: | ||||||
| """Returns the criterion for filtering eigenstates/eigenvalues.""" | ||||||
| return self._eigensolver.filter_criterion | ||||||
|
|
||||||
| @filter_criterion.setter | ||||||
| def filter_criterion( | ||||||
| self, | ||||||
| filter_criterion: Callable[[list | np.ndarray, float, ListOrDict[float] | None], bool], | ||||||
|
t-imamichi marked this conversation as resolved.
Outdated
|
||||||
| ) -> 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_operator_eigenvalues = 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.
|
||||||
| self._eigenstate = value | ||||||
Uh oh!
There was an error while loading. Please reload this page.