Skip to content
This repository was archived by the owner on Dec 7, 2021. It is now read-only.

Commit 41d9a15

Browse files
paulineollitraultPanagiotis Barkoutsospbarkmrossinekstefan-woerner
authored
Excited States algorithms and support for Chemistry (#1354)
* ground state min eigensolver interface * fix small things style * added the molecule object with the right properties * minor fix molecule * excited state calculation added * EOMvqe added * ground state interface minimum eigensolver * Add MinimumEigensolver interface to VQEAdapt * Implement the AdaptVQEGroundStateCalculation class This properly implements the AdaptVQEGroundStateCalculation class. The idea of this class is to allow easy use of the VQEAdapt algorithm which was previously extended to support the MinimumEigensolver interface. This Calculation class is solely for the use with this algorithm which is why it does not support setting a different solver. Instead, it requires setting a QuantumInstance object through its initializer. The changes which this requires include the following: - fixing the GroundStateCalculation class - fixing the MinEigensolverGroundStateCalculation class Furthermore, a very basic unittest for this change was added. * comments * initial bopes sampler * naming * compute eigenvalue MinEigensolver works * return raw results until I make the GroundStateResult * now the fermionic transformation returns a molecular ground state result working with mineigensolver result * added TODOs * rename GSC files * add init to qubit_transformations * fix lint in bosonic_trafo and qubit_op_trafo * update (MES)GSC to new structure * rm empty orbital optimization file * Fix init * Implement returns_groundstate and fix some lints * Rewrite AdaptVQEGSCalc. deriving from MESGSCalc. * Add TODO about deprecating qiskit.chemistry.algorithms module * Revert "Add MinimumEigensolver interface to VQEAdapt" This reverts commit 362843b. * Properly deprecate VQEAdapt * Port VQEAdapt to AdaptVQE (based on a GroundStateCalculation) This properly refactors the old qiskit.chemistry.algorithms.minimum_eigen_solver.VQEAdapt into the new qiskit.chemistry.ground_state_calculation.AdaptVQE class which implements the new GroundStateCalculation interface. The name change is intentional because the new name is in-line with the literature on AdaptVQE. The old name was presumably intentional to highlight its relation to VQE. The unittests for VQEAdapt are ported accordingly. * Some minor corrections/updates * Rename AdaptVQE files * Add optional custom_excitation_pool argument to AdaptVQE computation method * Work on FermionicTransformation and related objs - add interpet method to QubitOperatorTransformation and FermionicTransformation - remove deprecated method `_process_..._deprecated` - deprecate Hamiltonian and ChemistryOperator * documentation added * fixes in ground state * patch MES result to GSC result instead of returning a tuple * files fixes for GSC interface * rm utf8 headers * fix spell, lint, mypy * Remove `custom_excitation_pool` from AdaptVQE `compute_ground_state` function Rather than ignoring the arguments given by the interface, we can remove this additional argument in favor of enabling the user to set this custom excitation pool through the `MESFactory`. An example on how to achieve such a thing can be seen in the corresponding unittest. * fix mypy * fix lint * Re-enable DeprecationWarnings after VQEAdapt has been initialized * Fixes several minor nit-picks - copyright years - faulty renames - faulty merge side-effects - missing setters * make MESFactory an interface only * fix copyright years * derive from MESFactory and update docs * update docstrings and add molecule_info * consistent naming in ``ground(_)state`` * fix spell * more spell, deprecate MGSE * fix deprecation * more style * test fixes * fixes * [WIP] basic Result-interfaces This adds the following interfaces: - qiskit.chemistry.ChemistryResult(AlgorithmResult) - qiskit.chemistry.ground_state_calculation.GroundStateResult(ChemistryResult) - qiskit.chemistry.ground_state_calculation.FermionicGroundStateResult(GroundStateResult) The logic is as follows: ChemistryResult and GroundStateResult are empty interfaces which define a hierarchy for the result classes. They provide a useful granularity for type checking. Once more subclasses are added we can extract common functionality up into the stack as needed. The FermionicGroundStateResult currently is just a port of the old MolecularChemistryResult and MolecularGroundStateResult. Both of these classes are deprecated in this commit. Since this class is currently specific to the GroundStateCalculation it is part of that module. This is, however, subject to change. * Remove BosonicTransformation from this PR The BosonicTransformation will be added in a separate PR aiming to refactor the respective modules. * AdaptVQE actually supports aux_operators * [wip] resolve cyclic import problems Having a `Result` class in either the `ground_state_calculations` or `qubit_operator_transformations` modules leads to a coupling of the two modules that is too tight. I.e. we run into cyclic imports whenever we try to run any code because the `QubitOpTransformation` class needs to load the `Result` class while at the same time it needs to be available in the `GroundStateCalculation` class. Thus, when an additional coupling in between these two modules is created, we have cyclic import. Thus, we drop one level of granularity and only provide a single result-interface on the `qiskit.chemistry` level, here, called `ChemistryResult` (open for discussion). I also moved the `DipoleTuple` to this level to simplify its usage in the other classes. * Make AdaptVQE use the FermionicGSResult * Use FermionicGroundStateResult in MinimumEigensolverGroundStateCalculation * Fix mypy * Filter DeprecationWarnings in unittests This filters all of the DeprecationWarnigns introduced in this PR. In 3 months from now we can remove these tests once the corresponding code is also removed. This commit also adds TODO labels to all of these unittest files which will have to be migrated to work within the new framework. * Add TODO in AdaptVQE unittest * Add missing unittest imports I noticed that in some test files the unittest module is not imported and the `__main__` is not set accordingly. If we do not want to mix these changes into this PR, we can simply revert this commit. * mypy fix * unused code * Create qiskit.chemistry.results module * Replace interpret() with add_context() in QubitOperatorTransformations Instead of an interpret() function, the QubitOperatorTransformation interface defines an add_context() function which is used to augment the given StateResult object with information based on the transformation's context. * Fix GroundStateCalculation classes to work with the results interface * Revert faulty change in github workflow * unitests WIP first commit * remove deprecation suppressing from new tests * support additional aux ops and conv to dict * fix aux_ops=None * lint, style * more test * fixes in test * fix style * fix mypy * fix mypy * fixes in fermionic trafo * remove editor created redundant file * resolved tests * docstring fix * fix error & specify type hint * change typehint Any -> FermionicOp * add missing imports * spell * suggestions from code review * consistent use in .keys() * type hints, minor improvements * Rethink the qiskit.chemistry.results After some discussion we decided to rethink parts of the qiskit.chemistry.results interfaces. We want to minimize the differentiation between grround and excited states and let only the concrete `QubitOperatorTransformation` handle the fermionic and bosonic differentiation. Thus, I apply the following changes: * provide a single `EigenstateResult` which can be either a ground or excited state * derive `ElectronicStructureResult` (prev. `FermionicResult`) from this * use the `FermionicTransformation.interpret()` method to map a general `EigenstateResult` to the type specific for the transformation With the last change we also align the `qiskit.chemistry` module further with the `qiskit.optimization` module where we also use `interpret()` rather than `add_context()` methods (which was the name we intended to use prior to this commit). * Remove unneeded DeprecationWarning from AdaptVQEResult * Update some docstrings * fix lint * revert back to lists of aux_ops * Update qiskit/chemistry/ground_state_calculation/adapt_vqe.py Co-authored-by: Max Rossmannek <max.rossmannek@uzh.ch> * apply suggestions from code review * change typehint to List[float] * Update qiskit/chemistry/core/hamiltonian.py Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com> * test fixes after code review * excited state interface for matching the ground state interface and handling both electronic and vibrational states * Rename aux_values to aux_operator_eigenvalues This naming is consistent with the EigensolverResult and MinimumEigensolverResult classes. * Remove leftover from dict-style aux_operators * Add an `evaluate_operators` method to the GroundStateCalculation This method can be used to evaluate any additional auxiliary operators after the GSC has finished. This will be necessary especially in the excited state calculations and is in general a nice option for the user to have. The method is similar to how the `VQE` evaluates auxiliary operators internally. However, it can also deal with `MinimumEigensolver`s which do not use a `QuantumInstance`. A curiousity arose because the `VQE` appears to wrap the auxiliary operator results into lists multiple times. In order to ensure interoperability the same is done here. The `AdaptVQE` now derives off of the `MinimumEigensolverGSC` because there was no obvious drawback to this and the benefit of reusing this new method was welcome. Unittests have been added to test the new functionality. * fix lint * Remove erronous TODO * Enforce a FermionicTransformation in the VQEUCCSDFactory * Do not enforce VQEUCCSDFactory type in AdaptVQE Since we check for the VQE and UCCSD types anyways we shouldn't force the user to subclass this factory. * Reuse the VQE object during AdaptVQE * Expose molecule_info and qubit_mapping publicly * fix lint * fixes in tests * fixes in tests and revert to molecule_methods * remove two duplicate tests * Expose some VQE arguments in the VQEUCCSDFactory As discussed, we now expose some of the VQE arguments through this factory in order to allow greater flexibility for the user. * test commit * fix spell * fix bugs qeom code and first version of test for numerical qeom * added the build_hopping_operator capability in the transformation * modified results to take excited states components * reverted due to missing part of the test uccsd_HF * remove test EOM todos * lint * more lint * more lint * Prepare EigenstateResult to handle ground and excited states * Deprecate the Enums in the chemistry.core module * Also populate eigenstates in ground state calculations * Add factory for NumPyMinimumEigensolver * Implement `_filter_criterion` in FermionicTransformation * Extract default filter_criterion into interface Rather than checking for a private method being implemented we can obtain the default filter_criterion cleanly. This makes sense because any transformation in theory could implement a default filter. However, we return None in case it is not implemented. * fixing qeom code * Make use of default filter criterion configurable * Check state's type before making at a StateFn * Use `supports_aux_ops` in `returns_groundstate` * Replace Any type-hint where not really necessary The reason for making it a union of lists rather than a list of a union is to ensure that no mixed lists are allowed. * Do not use legacy Operator in new interface The WeightedPauliOp is a legacy operator and should not be used in this new interface. Instead, we now convert the operators to the OperatorFlow before returning them to ensure we only use the new operator types. * fix the eigenstate_result and electronic_structure_result to work with excited states and test eom with Numpy eigensolver for the ground state * clean qeom code * tests for numerical qeom * change of the ExcitedStatesCalculation init so that it does not have a GSC * Except (Minimum)EigensolverResults in interpret() To provide more user-flexibility and better compatibility with the Aqua result classes, the interpret() method is able to handle (Minimum)EigensolverResult classes as well as the EigenstateResult. * Fix tests to work with OperatorBase rather than WeightedPauliOperator * fix es_factory and additional information in FermionicTransformation for Analytical qEOM * rm WPO support in trafo, add test for aux_ops * Fix docstring * Fix aux_op particle-hole conversion * Extend ElectronicStructureResult to work with excited state calculations Since an electronic structure can consist of multiple states and during excited state calculations we obtain energies and auxiliary operator evaluations for each investigated state we expose all finally interpreted result properties as Lists where the first entry should always reflect the ground state properties. * fix auxiliary operators * reformatting of electronic structure results print * fix linting * fix mypy * Restructure excited states code - moving modules - renaming classes - adapting tests * more mypy fixes * final mypy fixes * add use_default_filter_criterion argument to NumPyEigensolverFactory * fix tests * fix lint and spell * fix lint * fix unittests * fix test * Fix typos in reno * added a release note * Do not use the default_filter_criterion for excited states Since we opted to make the default filter criterion of the fermionic case filter non-singlet states this kind of misses the point in the excirted states cases. Thus we now provide a custom filter in the test. For the backlog we should consider a better implementation of the default filter which can handle this automatically. * Fix test * Do not append line to README * Fix some docstrings and copyright years * Fix test * Use aqua_globals.random_seed in bopes test * Fix lint Co-authored-by: Panagiotis Barkoutsos <bpa@zurich.ibm.com> Co-authored-by: Panagiotis Barkoutsos <pbarkoutsos@gmail.com> Co-authored-by: Max Rossmannek <oss@zurich.ibm.com> Co-authored-by: Stefan Woerner <WOR@zurich.ibm.com> Co-authored-by: Cryoris <jules.gacon@googlemail.com> Co-authored-by: Julien Gacon <gaconju@gmail.com> Co-authored-by: Manoel Marques <manoel.marques@ibm.com> Co-authored-by: Anton Dekusar <adekusar@ie.ibm.com> Co-authored-by: Anton Dekusar <62334182+adekusar-drl@users.noreply.github.com> Co-authored-by: Max Rossmannek <max.rossmannek@uzh.ch> Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com> Co-authored-by: Mario Motta <mario@marios-mbp.almaden.ibm.com> Co-authored-by: Stefan Woerner <41292468+stefan-woerner@users.noreply.github.com>
1 parent f93bb03 commit 41d9a15

28 files changed

+1313
-152
lines changed

.pylintdict

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ fcompiler
218218
fd
219219
fermionic
220220
fermionicoperator
221+
fermionictransformation
221222
fermionicdriver
222223
fermions
223224
fi

qiskit/aqua/algorithms/eigen_solvers/numpy_eigen_solver.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ def _run(self):
285285
self._ret['eigvecs'] = np.array(eigvecs)
286286
self._ret['eigvals'] = np.array(eigvals)
287287
self._ret['energies'] = np.array(energies)
288+
# conversion to np.array breaks in case of aux_ops
289+
self._ret['aux_ops'] = aux_ops
288290

289291
self._k = k_orig
290292

qiskit/aqua/operators/legacy/common.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def evolution_instruction(pauli_list, evo_time, num_time_slices,
384384
return qc.to_instruction()
385385

386386

387-
def commutator(op_a, op_b, op_c=None, threshold=1e-12):
387+
def commutator(op_a, op_b, op_c=None, sign=-1, threshold=1e-12):
388388
r"""
389389
Compute commutator of `op_a` and `op_b` or
390390
the symmetric double commutator of `op_a`, `op_b` and `op_c`.
@@ -401,6 +401,7 @@ def commutator(op_a, op_b, op_c=None, threshold=1e-12):
401401
op_a (WeightedPauliOperator): operator a
402402
op_b (WeightedPauliOperator): operator b
403403
op_c (Optional(WeightedPauliOperator)): operator c
404+
sign (int): -1 is anti-commute, 1 is commute
404405
threshold (float): the truncation threshold
405406
406407
Returns:
@@ -413,7 +414,7 @@ def commutator(op_a, op_b, op_c=None, threshold=1e-12):
413414
op_ba = op_b * op_a
414415

415416
if op_c is None:
416-
res = op_ab - op_ba
417+
res = op_ab + sign * op_ba
417418
else:
418419
op_ac = op_a * op_c
419420
op_ca = op_c * op_a
@@ -427,7 +428,7 @@ def commutator(op_a, op_b, op_c=None, threshold=1e-12):
427428

428429
tmp = (op_bac + op_cab + op_acb + op_bca)
429430
tmp = 0.5 * tmp
430-
res = op_abc + op_cba - tmp
431+
res = op_abc + op_cba + sign * tmp
431432

432433
res.simplify()
433434
res.chop(threshold)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2020.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""Excited states calculation algorithms."""
14+
15+
from .excited_states_solver import ExcitedStatesSolver
16+
from .qeom import QEOM
17+
from .eigensolver_factories import EigensolverFactory, NumPyEigensolverFactory
18+
from .excited_states_eigensolver import ExcitedStatesEigensolver
19+
20+
__all__ = ['ExcitedStatesSolver',
21+
'ExcitedStatesEigensolver',
22+
'EigensolverFactory',
23+
'NumPyEigensolverFactory',
24+
'QEOM'
25+
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2020.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""Factories that create an eigensolver based on a qubit transformation."""
14+
15+
16+
from .eigensolver_factory import EigensolverFactory
17+
from .numpy_eigensolver_factory import NumPyEigensolverFactory
18+
19+
__all__ = ['EigensolverFactory',
20+
'NumPyEigensolverFactory'
21+
]
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2020.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""The eigensolver factory for excited states calculation algorithms."""
14+
15+
from abc import ABC, abstractmethod
16+
from qiskit.aqua.algorithms import Eigensolver
17+
from qiskit.chemistry.transformations import Transformation
18+
19+
20+
class EigensolverFactory(ABC):
21+
"""A factory to construct a eigensolver based on a qubit operator transformation."""
22+
23+
@abstractmethod
24+
def get_solver(self, transformation: Transformation) -> Eigensolver:
25+
"""Returns a eigensolver, based on the qubit operator transformation.
26+
27+
Args:
28+
transformation: The qubit operator transformation.
29+
30+
Returns:
31+
An eigensolver suitable to compute the excited states of the molecule transformed
32+
by ``transformation``.
33+
"""
34+
raise NotImplementedError
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2020.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""The numpy eigensolver factory for ground+excited states calculation algorithms."""
14+
15+
from typing import Optional, Union, List, Callable
16+
import numpy as np
17+
18+
from qiskit.aqua.algorithms import Eigensolver, NumPyEigensolver
19+
from qiskit.chemistry.transformations import FermionicTransformation
20+
from qiskit.aqua.utils.validation import validate_min
21+
22+
from .eigensolver_factory import EigensolverFactory
23+
24+
25+
class NumPyEigensolverFactory(EigensolverFactory):
26+
"""A factory to construct a NumPyEigensolver."""
27+
28+
def __init__(self,
29+
filter_criterion: Callable[[Union[List, np.ndarray], float, Optional[List[float]]],
30+
bool] = None,
31+
k: int = 100,
32+
use_default_filter_criterion: bool = False) -> None:
33+
"""
34+
Args:
35+
filter_criterion: callable that allows to filter eigenvalues/eigenstates. The minimum
36+
eigensolver is only searching over feasible states and returns an eigenstate that
37+
has the smallest eigenvalue among feasible states. The callable has the signature
38+
`filter(eigenstate, eigenvalue, aux_values)` and must return a boolean to indicate
39+
whether to consider this value or not. If there is no
40+
feasible element, the result can even be empty.
41+
k: How many eigenvalues are to be computed, has a min. value of 1.
42+
use_default_filter_criterion: whether to use the transformation's default filter
43+
criterion if ``filter_criterion`` is ``None``.
44+
"""
45+
self._filter_criterion = filter_criterion
46+
self._k = k # pylint:disable=invalid-name
47+
self._use_default_filter_criterion = use_default_filter_criterion
48+
49+
@property
50+
def filter_criterion(self) -> Callable[[Union[List, np.ndarray], float, Optional[List[float]]],
51+
bool]:
52+
""" returns filter criterion """
53+
return self._filter_criterion
54+
55+
@filter_criterion.setter
56+
def filter_criterion(self, value: Callable[[Union[List, np.ndarray], float,
57+
Optional[List[float]]], bool]) -> None:
58+
""" sets filter criterion """
59+
self._filter_criterion = value
60+
61+
@property
62+
def k(self) -> int:
63+
""" returns k (number of eigenvalues requested) """
64+
return self._k
65+
66+
@k.setter
67+
def k(self, k: int) -> None:
68+
""" set k (number of eigenvalues requested) """
69+
validate_min('k', k, 1)
70+
self._k = k
71+
72+
@property
73+
def use_default_filter_criterion(self) -> bool:
74+
""" returns whether to use the default filter criterion """
75+
return self._use_default_filter_criterion
76+
77+
@use_default_filter_criterion.setter
78+
def use_default_filter_criterion(self, value: bool) -> None:
79+
""" sets whether to use the default filter criterion """
80+
self._use_default_filter_criterion = value
81+
82+
def get_solver(self, transformation: FermionicTransformation) -> Eigensolver:
83+
"""Returns a NumPyEigensolver with the desired filter
84+
85+
Args:
86+
transformation: a fermionic qubit operator transformation.
87+
88+
Returns:
89+
A NumPyEigensolver suitable to compute the ground state of the molecule
90+
transformed by ``transformation``.
91+
"""
92+
filter_criterion = self._filter_criterion
93+
if not filter_criterion and self._use_default_filter_criterion:
94+
filter_criterion = transformation.get_default_filter_criterion()
95+
96+
npe = NumPyEigensolver(filter_criterion=filter_criterion, k=self.k)
97+
return npe
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2020.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""The calculation of excited states via an Eigensolver algorithm"""
14+
15+
import logging
16+
17+
from typing import List, Union, Optional, Any
18+
19+
from qiskit.aqua.algorithms import Eigensolver
20+
from qiskit.aqua.operators import WeightedPauliOperator
21+
from qiskit.chemistry import FermionicOperator
22+
from qiskit.chemistry.drivers import BaseDriver
23+
from qiskit.chemistry.results import EigenstateResult
24+
from qiskit.chemistry.transformations import Transformation
25+
from qiskit.chemistry.results import ElectronicStructureResult, VibronicStructureResult
26+
27+
from .excited_states_solver import ExcitedStatesSolver
28+
from .eigensolver_factories import EigensolverFactory
29+
30+
logger = logging.getLogger(__name__)
31+
32+
33+
class ExcitedStatesEigensolver(ExcitedStatesSolver):
34+
"""The calculation of excited states via an Eigensolver algorithm"""
35+
36+
def __init__(self, transformation: Transformation,
37+
solver: Union[Eigensolver, EigensolverFactory]) -> None:
38+
"""
39+
40+
Args:
41+
transformation: Qubit Operator Transformation
42+
solver: Minimum Eigensolver or MESFactory object.
43+
"""
44+
self._transformation = transformation
45+
self._solver = solver
46+
47+
@property
48+
def solver(self) -> Union[Eigensolver, EigensolverFactory]:
49+
"""Returns the minimum eigensolver or factory."""
50+
return self._solver
51+
52+
@solver.setter
53+
def solver(self, solver: Union[Eigensolver, EigensolverFactory]) -> None:
54+
"""Sets the minimum eigensolver or factory."""
55+
self._solver = solver
56+
57+
@property
58+
def transformation(self) -> Transformation:
59+
"""Returns the transformation used to obtain a qubit operator from the molecule."""
60+
return self._transformation
61+
62+
@transformation.setter
63+
def transformation(self, transformation: Transformation) -> None:
64+
"""Sets the transformation used to obtain a qubit operator from the molecule."""
65+
self._transformation = transformation
66+
67+
def solve(self, driver: BaseDriver,
68+
aux_operators: Optional[List[Any]] = None
69+
) -> Union[ElectronicStructureResult, VibronicStructureResult]:
70+
"""Compute Ground and Excited States properties.
71+
72+
Args:
73+
driver: a chemistry driver object which defines the chemical problem that is to be
74+
solved by this calculation.
75+
aux_operators: Additional auxiliary operators to evaluate. Must be of type
76+
``FermionicOperator`` if the qubit transformation is fermionic and of type
77+
``BosonicOperator`` it is bosonic.
78+
79+
Raises:
80+
NotImplementedError: If an operator in ``aux_operators`` is not of type
81+
``FermionicOperator``.
82+
83+
Returns:
84+
An eigenstate result. Depending on the transformation this can be an electronic
85+
structure or bosonic result.
86+
"""
87+
if aux_operators is not None:
88+
if any(not isinstance(op, (WeightedPauliOperator, FermionicOperator))
89+
for op in aux_operators):
90+
raise NotImplementedError('Currently only fermionic problems are supported.')
91+
92+
# get the operator and auxiliary operators, and transform the provided auxiliary operators
93+
# note that ``aux_operators`` contains not only the transformed ``aux_operators`` passed
94+
# by the user but also additional ones from the transformation
95+
operator, aux_operators = self.transformation.transform(driver, aux_operators)
96+
97+
if isinstance(self._solver, EigensolverFactory):
98+
# this must be called after transformation.transform
99+
solver = self._solver.get_solver(self.transformation)
100+
else:
101+
solver = self._solver
102+
103+
# if the eigensolver does not support auxiliary operators, reset them
104+
if not solver.supports_aux_operators():
105+
aux_operators = None
106+
107+
raw_es_result = solver.compute_eigenvalues(operator, aux_operators)
108+
109+
eigenstate_result = EigenstateResult()
110+
eigenstate_result.raw_result = raw_es_result
111+
eigenstate_result.eigenenergies = raw_es_result.eigenvalues
112+
eigenstate_result.eigenstates = raw_es_result.eigenstates
113+
eigenstate_result.aux_operator_eigenvalues = raw_es_result.aux_operator_eigenvalues
114+
result = self.transformation.interpret(eigenstate_result)
115+
return result
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2020.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
""" The excited states calculation interface """
14+
15+
from abc import ABC, abstractmethod
16+
from typing import List, Optional, Union
17+
18+
from qiskit.chemistry.drivers import BaseDriver
19+
from qiskit.chemistry import FermionicOperator, BosonicOperator
20+
from qiskit.chemistry.results import ElectronicStructureResult, VibronicStructureResult
21+
22+
23+
class ExcitedStatesSolver(ABC):
24+
"""The excited states calculation interface"""
25+
26+
@abstractmethod
27+
def solve(self, driver: BaseDriver,
28+
aux_operators: Optional[Union[List[FermionicOperator],
29+
List[BosonicOperator]]] = None
30+
) -> Union[ElectronicStructureResult, VibronicStructureResult]:
31+
"""Compute the excited states energies of the molecule that was supplied via the driver.
32+
Args:
33+
driver: a chemistry driver object which defines the chemical problem that is to be
34+
solved by this calculation.
35+
aux_operators: Additional auxiliary operators to evaluate. Must be of type
36+
``FermionicOperator`` if the qubit transformation is fermionic and of type
37+
``BosonicOperator`` it is bosonic.
38+
Returns:
39+
an eigenstate result
40+
"""
41+
raise NotImplementedError()

0 commit comments

Comments
 (0)