-
Notifications
You must be signed in to change notification settings - Fork 3k
Time Evolution Framework with primitives. #8681
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
Merged
mergify
merged 31 commits into
Qiskit:main
from
dlasecki:evolution-framework-primitives
Sep 13, 2022
Merged
Changes from 11 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
e3233b7
Implemented observables_evaluator.py with primitives.
d71f50b
Added evolvers problems and interfaces to time_evolvers package.
7a7c82b
Mostly updated trotter_qrte.py to use primitives.
54afe25
Added observables_evaluator.py that uses primitives.
d2b67d9
Added observables_evaluator.py that uses primitives.
c1276d2
Updated trotter_qrte.py to use primitives.
e06c6c2
Updated imports
5a9bebe
Updated typehints and limited use of opflow.
356deae
Updated typehints and limited use of opflow.
14ba35d
Removed files out of scope for this PR.
4cf6f61
Added annotations import.
604944c
Applied some CR comments.
23821e0
Added reno.
a2960b2
Accepting Statevector.
9b5f50a
Added attributes docs.
107dc2b
Merge branch 'main' into evolution-framework-primitives
manoelmarques 387ce78
Add pending deprecation for evolvers
manoelmarques a7e2f60
Renamed classes and linked to algorithms init.
34c2deb
Merge remote-tracking branch 'origin/evolution-framework-primitives' …
5c87255
fix docstring
manoelmarques d03bddf
Improved reno.
a656db0
Merge branch 'main' into evolution-framework-primitives
7680019
Code refactoring.
1dce473
Black fix.
d3c601e
Applied CR comments.
4795b45
Add deprecation msg to evolvers package
manoelmarques ce6d828
Merge branch 'main' into evolution-framework-primitives
0552379
Merge branch 'main' into evolution-framework-primitives
woodsp-ibm 6e834f0
Merge branch 'main' into evolution-framework-primitives
d9c8d84
Merge branch 'main' into evolution-framework-primitives
cc7d678
Merge branch 'main' into evolution-framework-primitives
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| # 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. | ||
|
|
||
| """Evolution problem class.""" | ||
| from __future__ import annotations | ||
| from typing import Dict | ||
|
|
||
| from qiskit import QuantumCircuit | ||
| from qiskit.circuit import Parameter | ||
| from qiskit.opflow import PauliSumOp | ||
| from ..list_or_dict import ListOrDict | ||
| from ...quantum_info.operators.base_operator import BaseOperator | ||
|
|
||
|
|
||
| class EvolutionProblem: | ||
| """Evolution problem class. | ||
|
|
||
| This class is the input to time evolution algorithms and must contain information on the total | ||
| evolution time, a quantum state to be evolved and under which Hamiltonian the state is evolved. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| hamiltonian: BaseOperator | PauliSumOp, | ||
| time: float, | ||
| initial_state: QuantumCircuit | None = None, | ||
| aux_operators: ListOrDict[BaseOperator | PauliSumOp] | None = None, | ||
| truncation_threshold: float = 1e-12, | ||
| t_param: Parameter | None = None, | ||
| param_value_dict: Dict[Parameter, complex] | ||
|
dlasecki marked this conversation as resolved.
Outdated
|
||
| | None = None, # parametrization will become supported in BaseOperator soon | ||
| ): | ||
| """ | ||
| Args: | ||
| hamiltonian: The Hamiltonian under which to evolve the system. | ||
| time: Total time of evolution. | ||
| initial_state: The quantum state to be evolved for methods like Trotterization. | ||
| For variational time evolutions, where the evolution happens in an ansatz, | ||
| this argument is not required. | ||
| aux_operators: Optional list of auxiliary operators to be evaluated with the | ||
| evolved ``initial_state`` and their expectation values returned. | ||
| truncation_threshold: Defines a threshold under which values can be assumed to be 0. | ||
| Used when ``aux_operators`` is provided. | ||
| t_param: Time parameter in case of a time-dependent Hamiltonian. This | ||
| free parameter must be within the ``hamiltonian``. | ||
| param_value_dict: Maps free parameters in the problem to values. Depending on the | ||
| algorithm, it might refer to e.g. a Hamiltonian or an initial state. | ||
|
Cryoris marked this conversation as resolved.
Outdated
|
||
|
|
||
| Raises: | ||
| ValueError: If non-positive time of evolution is provided. | ||
| """ | ||
|
|
||
| self.t_param = t_param | ||
| self.param_value_dict = param_value_dict | ||
| self.hamiltonian = hamiltonian | ||
| self.time = time | ||
| self.initial_state = initial_state | ||
| self.aux_operators = aux_operators | ||
| self.truncation_threshold = truncation_threshold | ||
|
dlasecki marked this conversation as resolved.
|
||
|
|
||
| @property | ||
| def time(self) -> float: | ||
| """Returns time.""" | ||
| return self._time | ||
|
|
||
| @time.setter | ||
| def time(self, time: float) -> None: | ||
| """ | ||
| Sets time and validates it. | ||
|
|
||
| Raises: | ||
| ValueError: If time is not positive. | ||
| """ | ||
| if time <= 0: | ||
| raise ValueError(f"Evolution time must be > 0 but was {time}.") | ||
| self._time = time | ||
|
|
||
| def validate_params(self) -> None: | ||
| """ | ||
| Checks if all parameters present in the Hamiltonian are also present in the dictionary | ||
| that maps them to values. | ||
|
|
||
| Raises: | ||
| ValueError: If Hamiltonian parameters cannot be bound with data provided. | ||
| """ | ||
| if isinstance(self.hamiltonian, PauliSumOp) and self.hamiltonian.parameters: | ||
| raise ValueError("A global parametrized coefficient for PauliSumOp is not allowed.") | ||
|
dlasecki marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # This code is part of Qiskit. | ||
| # | ||
| # (C) Copyright IBM 2021, 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. | ||
|
|
||
| """Class for holding evolution result.""" | ||
| from __future__ import annotations | ||
| from typing import Tuple | ||
|
|
||
| from qiskit import QuantumCircuit | ||
| from qiskit.algorithms.list_or_dict import ListOrDict | ||
| from ..algorithm_result import AlgorithmResult | ||
|
|
||
|
|
||
| class EvolutionResult(AlgorithmResult): | ||
| """Class for holding evolution result.""" | ||
|
|
||
| def __init__( | ||
| self, | ||
| evolved_state: QuantumCircuit, | ||
| aux_ops_evaluated: ListOrDict[Tuple[complex, complex]] | None = None, | ||
|
dlasecki marked this conversation as resolved.
Outdated
|
||
| ): | ||
| """ | ||
| Args: | ||
| evolved_state: An evolved quantum state. | ||
| aux_ops_evaluated: Optional list of observables for which expected values on an evolved | ||
| state are calculated. These values are in fact tuples formatted as (mean, standard | ||
| deviation). | ||
| """ | ||
|
|
||
| self.evolved_state = evolved_state | ||
| self.aux_ops_evaluated = aux_ops_evaluated | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # This code is part of Qiskit. | ||
| # | ||
| # (C) Copyright IBM 2021, 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. | ||
|
|
||
| """Interface for Quantum Imaginary Time Evolution.""" | ||
|
|
||
| from abc import ABC, abstractmethod | ||
|
|
||
| from .evolution_problem import EvolutionProblem | ||
| from .evolution_result import EvolutionResult | ||
|
|
||
|
|
||
| class ImaginaryEvolver(ABC): | ||
| """Interface for Quantum Imaginary Time Evolution.""" | ||
|
|
||
| @abstractmethod | ||
| def evolve(self, evolution_problem: EvolutionProblem) -> EvolutionResult: | ||
| r"""Perform imaginary time evolution :math:`\exp(-\tau H)|\Psi\rangle`. | ||
|
|
||
| Evolves an initial state :math:`|\Psi\rangle` for an imaginary time :math:`\tau` | ||
| under a Hamiltonian :math:`H`, as provided in the ``evolution_problem``. | ||
|
|
||
| Args: | ||
| evolution_problem: The definition of the evolution problem. | ||
|
|
||
| Returns: | ||
| Evolution result which includes an evolved quantum state. | ||
| """ | ||
| raise NotImplementedError() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # This code is part of Qiskit. | ||
| # | ||
| # (C) Copyright IBM 2021, 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. | ||
|
|
||
| """Interface for Quantum Real Time Evolution.""" | ||
|
|
||
| from abc import ABC, abstractmethod | ||
|
|
||
| from .evolution_problem import EvolutionProblem | ||
| from .evolution_result import EvolutionResult | ||
|
|
||
|
|
||
| class RealEvolver(ABC): | ||
| """Interface for Quantum Real Time Evolution.""" | ||
|
|
||
| @abstractmethod | ||
| def evolve(self, evolution_problem: EvolutionProblem) -> EvolutionResult: | ||
| r"""Perform real time evolution :math:`\exp(-i t H)|\Psi\rangle`. | ||
|
|
||
| Evolves an initial state :math:`|\Psi\rangle` for a time :math:`t` | ||
| under a Hamiltonian :math:`H`, as provided in the ``evolution_problem``. | ||
|
|
||
| Args: | ||
| evolution_problem: The definition of the evolution problem. | ||
|
|
||
| Returns: | ||
| Evolution result which includes an evolved quantum state. | ||
| """ | ||
| raise NotImplementedError() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # 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. |
101 changes: 101 additions & 0 deletions
101
test/python/algorithms/time_evolvers/test_evolution_problem.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| # 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. | ||
|
|
||
| """Test evolver problem class.""" | ||
| import unittest | ||
|
|
||
| from test.python.algorithms import QiskitAlgorithmsTestCase | ||
| from ddt import data, ddt, unpack | ||
| from numpy.testing import assert_raises | ||
| from qiskit.algorithms.time_evolvers.evolution_problem import EvolutionProblem | ||
| from qiskit.quantum_info import Pauli, SparsePauliOp | ||
| from qiskit.circuit import Parameter | ||
| from qiskit.opflow import Y, Z, One, X, Zero, PauliSumOp | ||
|
|
||
|
|
||
| @ddt | ||
| class TestEvolutionProblem(QiskitAlgorithmsTestCase): | ||
| """Test evolver problem class.""" | ||
|
|
||
| def test_init_default(self): | ||
| """Tests that all default fields are initialized correctly.""" | ||
| hamiltonian = Y | ||
| time = 2.5 | ||
| initial_state = One | ||
|
|
||
| evo_problem = EvolutionProblem(hamiltonian, time, initial_state) | ||
|
|
||
| expected_hamiltonian = Y | ||
| expected_time = 2.5 | ||
| expected_initial_state = One | ||
| expected_aux_operators = None | ||
| expected_t_param = None | ||
| expected_param_value_dict = None | ||
|
|
||
| self.assertEqual(evo_problem.hamiltonian, expected_hamiltonian) | ||
| self.assertEqual(evo_problem.time, expected_time) | ||
| self.assertEqual(evo_problem.initial_state, expected_initial_state) | ||
| self.assertEqual(evo_problem.aux_operators, expected_aux_operators) | ||
| self.assertEqual(evo_problem.t_param, expected_t_param) | ||
| self.assertEqual(evo_problem.param_value_dict, expected_param_value_dict) | ||
|
|
||
| def test_init_all(self): | ||
| """Tests that all fields are initialized correctly.""" | ||
| t_parameter = Parameter("t") | ||
| hamiltonian = t_parameter * Z + Y | ||
| time = 2 | ||
| initial_state = One | ||
| aux_operators = [X, Y] | ||
| param_value_dict = {t_parameter: 3.2} | ||
|
|
||
| evo_problem = EvolutionProblem( | ||
| hamiltonian, | ||
| time, | ||
| initial_state, | ||
| aux_operators, | ||
| t_param=t_parameter, | ||
| param_value_dict=param_value_dict, | ||
| ) | ||
|
|
||
| expected_hamiltonian = Y + t_parameter * Z | ||
| expected_time = 2 | ||
| expected_initial_state = One | ||
| expected_aux_operators = [X, Y] | ||
| expected_t_param = t_parameter | ||
| expected_param_value_dict = {t_parameter: 3.2} | ||
|
|
||
| self.assertEqual(evo_problem.hamiltonian, expected_hamiltonian) | ||
| self.assertEqual(evo_problem.time, expected_time) | ||
| self.assertEqual(evo_problem.initial_state, expected_initial_state) | ||
| self.assertEqual(evo_problem.aux_operators, expected_aux_operators) | ||
| self.assertEqual(evo_problem.t_param, expected_t_param) | ||
| self.assertEqual(evo_problem.param_value_dict, expected_param_value_dict) | ||
|
|
||
| @data([Y, -1, One], [Y, -1.2, One], [Y, 0, One]) | ||
| @unpack | ||
| def test_init_errors(self, hamiltonian, time, initial_state): | ||
| """Tests expected errors are thrown on invalid time argument.""" | ||
| with assert_raises(ValueError): | ||
| _ = EvolutionProblem(hamiltonian, time, initial_state) | ||
|
|
||
| def test_validate_params(self): | ||
| """Tests expected errors are thrown on parameters mismatch.""" | ||
| param_x = Parameter("x") | ||
| with self.subTest(msg="Parameter missing in dict."): | ||
| hamiltonian = PauliSumOp(SparsePauliOp([Pauli("X"), Pauli("Y")]), param_x) | ||
| evolution_problem = EvolutionProblem(hamiltonian, 2, Zero) | ||
| with assert_raises(ValueError): | ||
| evolution_problem.validate_params() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
47 changes: 47 additions & 0 deletions
47
test/python/algorithms/time_evolvers/test_evolution_result.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # 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. | ||
| """Class for testing evolution result.""" | ||
| import unittest | ||
| from test.python.algorithms import QiskitAlgorithmsTestCase | ||
| from qiskit.algorithms.time_evolvers.evolution_result import EvolutionResult | ||
| from qiskit.opflow import Zero | ||
|
|
||
|
|
||
| class TestEvolutionResult(QiskitAlgorithmsTestCase): | ||
| """Class for testing evolution result and relevant metadata.""" | ||
|
|
||
| def test_init_state(self): | ||
| """Tests that a class is initialized correctly with an evolved_state.""" | ||
| evolved_state = Zero | ||
| evo_result = EvolutionResult(evolved_state=evolved_state) | ||
|
|
||
| expected_state = Zero | ||
| expected_aux_ops_evaluated = None | ||
|
|
||
| self.assertEqual(evo_result.evolved_state, expected_state) | ||
| self.assertEqual(evo_result.aux_ops_evaluated, expected_aux_ops_evaluated) | ||
|
|
||
| def test_init_observable(self): | ||
| """Tests that a class is initialized correctly with an evolved_observable.""" | ||
| evolved_state = Zero | ||
| evolved_aux_ops_evaluated = [(5j, 5j), (1.0, 8j), (5 + 1j, 6 + 1j)] | ||
| evo_result = EvolutionResult(evolved_state, evolved_aux_ops_evaluated) | ||
|
|
||
| expected_state = Zero | ||
| expected_aux_ops_evaluated = [(5j, 5j), (1.0, 8j), (5 + 1j, 6 + 1j)] | ||
|
|
||
| self.assertEqual(evo_result.evolved_state, expected_state) | ||
| self.assertEqual(evo_result.aux_ops_evaluated, expected_aux_ops_evaluated) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.