-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Slater determinant and fermionic Gaussian state initial states (#483
) * add QuadraticHamiltonian class * preparation of Slater determinants and fermionic Gaussian states * validate input * expose _fermionic_op as to_fermionic_op * use tuple labels and merge loops * update docs * add num_modes argument * document new errors * add num_modes property * update doc * spelling * mypy * from __future__ import annotations * add release note * trigger CI * fix spelling * update terra * split so each class has own file * fix comments and error messages, don't name registers * revert library init description * run copyright check * add release note * spelling * spelling and docs * make private functions hidden again * mypy * improve docs and error messages * split test file * add input validation * mypy * lint * add slater determinants test file * create utils module * test unsupported mappers fail gracefully * fix imports * raise NotImplementedError for unsupported mapper * improve docs * rewrite documentation * improve docs and error messages * factor out validation function * improve slater determinant docs * add tutorial notebook * typo * fix warning in notebook * edit notebook * comma * spelling and format * add note to QuadraticHamiltonian class * Update docs/tutorials/11_quadratic_hamiltonian_and_slater_determinants.ipynb Co-authored-by: Max Rossmannek <[email protected]> * add hyperlinks * update print output in notebook * Update releasenotes/notes/slater-53415163fff84313.yaml Co-authored-by: Steve Wood <[email protected]> * format * edit notebook kernel to satisfy CI * edit notebook * edit notebook to say creation instead of annihilation Co-authored-by: Panagiotis Barkoutsos <[email protected]> Co-authored-by: Manoel Marques <[email protected]> Co-authored-by: Max Rossmannek <[email protected]> Co-authored-by: Steve Wood <[email protected]> Co-authored-by: Max Rossmannek <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information
1 parent
a3bf369
commit 762fc0c
Showing
12 changed files
with
1,187 additions
and
5 deletions.
There are no files selected for viewing
This file contains 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
440 changes: 440 additions & 0 deletions
440
docs/tutorials/11_quadratic_hamiltonian_and_slater_determinants.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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
This file contains 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
173 changes: 173 additions & 0 deletions
173
qiskit_nature/circuit/library/initial_states/fermionic_gaussian_state.py
This file contains 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,173 @@ | ||
# 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. | ||
|
||
"""Fermionic Gaussian states.""" | ||
|
||
from typing import Optional, Sequence | ||
|
||
import numpy as np | ||
from qiskit import QuantumCircuit, QuantumRegister | ||
from qiskit_nature.converters.second_quantization import QubitConverter | ||
from qiskit_nature.mappers.second_quantization import JordanWignerMapper | ||
|
||
from .utils.givens_rotations import _prepare_fermionic_gaussian_state_jordan_wigner | ||
|
||
|
||
def _validate_transformation_matrix( | ||
mat: np.ndarray, rtol: float = 1e-5, atol: float = 1e-8 | ||
) -> None: | ||
if not len(mat.shape) == 2: | ||
raise ValueError( | ||
"transformation_matrix must be a 2-dimensional array. " | ||
f"Instead, got shape {mat.shape}." | ||
) | ||
|
||
n, p = mat.shape # pylint: disable=invalid-name | ||
if p != n * 2: | ||
raise ValueError( | ||
"transformation_matrix must have shape (n_orbitals, 2 * n_orbitals). " | ||
f"Instead, got shape {mat.shape}." | ||
) | ||
|
||
left = mat[:, :n] | ||
right = mat[:, n:] | ||
comm1 = left @ left.T.conj() + right @ right.T.conj() | ||
comm2 = left @ right.T + right @ left.T | ||
one = np.eye(n) | ||
zero = np.zeros((n, n)) | ||
if not np.allclose(comm1, one, rtol=rtol, atol=atol) or not np.allclose(comm2, zero): | ||
raise ValueError( | ||
"transformation_matrix does not describe a valid transformation " | ||
"of fermionic ladder operators. A valid matrix should have the block form " | ||
"[W1 W2] where W1 @ W1.T.conj() + W2 @ W2.T.conj() = I and " | ||
"W1 @ W2.T + W2 @ W1.T = 0." | ||
) | ||
|
||
|
||
class FermionicGaussianState(QuantumCircuit): | ||
r"""A circuit that prepares a fermionic Gaussian state. | ||
A fermionic Gaussian state is a state of the form | ||
.. math:: | ||
b^\dagger_1 \cdots b^\dagger_{N_p} \lvert \overline{\text{vac}} \rangle | ||
where | ||
.. math:: | ||
\begin{pmatrix} | ||
b^\dagger_1 \\ | ||
\vdots \\ | ||
b^\dagger_N \\ | ||
\end{pmatrix} | ||
= W | ||
\begin{pmatrix} | ||
a^\dagger_1 \\ | ||
\vdots \\ | ||
a^\dagger_N \\ | ||
a_1 \\ | ||
\vdots \\ | ||
a_N | ||
\end{pmatrix}, | ||
- :math:`a^\dagger_1, \ldots, a^\dagger_{N}` are the fermionic creation operators | ||
- :math:`W` is an :math:`N \times 2N` matrix such that | ||
:math:`b^\dagger_1, \ldots, b^\dagger_{N}` also satisfy the | ||
fermionic anticommutation relations | ||
- :math:`\lvert \overline{\text{vac}} \rangle` is the mutual 0-eigenvector of | ||
the operators :math:`\{b_j^\dagger b_j\}` | ||
The matrix :math:`W` has the block form | ||
.. math:: | ||
\begin{pmatrix} | ||
W_1 & W_2 | ||
\end{pmatrix} | ||
where :math:`W_1` and :math:`W_2` must satisfy | ||
.. math:: | ||
W_1 W_1^\dagger + W_2 W_2^\dagger = I \\ | ||
W_1 W_2^T + W_2 W_1^T = 0 | ||
The matrix :math:`W` is commonly obtained by calling the | ||
:meth:`~.QuadraticHamiltonian.diagonalizing_bogoliubov_transform` | ||
method of the :class:`~.QuadraticHamiltonian` class. | ||
This matrix is used to create circuits that prepare eigenstates of the | ||
quadratic Hamiltonian. | ||
Currently, only the Jordan-Wigner Transformation is supported. | ||
Reference: `arXiv:1711.05395`_ | ||
.. _arXiv:1711.05395: https://arxiv.org/abs/1711.05395 | ||
""" | ||
|
||
def __init__( | ||
self, | ||
transformation_matrix: np.ndarray, | ||
occupied_orbitals: Optional[Sequence[int]] = None, | ||
qubit_converter: QubitConverter = None, | ||
validate: bool = True, | ||
rtol: float = 1e-5, | ||
atol: float = 1e-8, | ||
**circuit_kwargs, | ||
) -> None: | ||
r""" | ||
Args: | ||
transformation_matrix: The matrix :math:`W` that specifies the coefficients of the | ||
new creation operators in terms of the original creation and annihilation operators. | ||
This matrix must satisfy special constraints; see the main body of the docstring | ||
of this class. | ||
occupied_orbitals: The pseudo-particle orbitals to fill. These refer to the indices | ||
of the operators :math:`\{b^\dagger_j\}` from the main body of the docstring | ||
of this function. The default behavior is to use the empty set of orbitals, | ||
which corresponds to a state with zero pseudo-particles. | ||
qubit_converter: a QubitConverter instance. | ||
validate: Whether to validate the inputs. | ||
rtol: Relative numerical tolerance for input validation. | ||
atol: Absolute numerical tolerance for input validation. | ||
circuit_kwargs: Keyword arguments to pass to the QuantumCircuit initializer. | ||
Raises: | ||
ValueError: transformation_matrix must be a 2-dimensional array. | ||
ValueError: transformation_matrix must have shape (n_orbitals, 2 * n_orbitals). | ||
NotImplementedError: Currently, only the Jordan-Wigner Transform is supported. | ||
Please use | ||
:class:`qiskit_nature.mappers.second_quantization.JordanWignerMapper` | ||
to construct the qubit mapper used to construct `qubit_converter`. | ||
""" | ||
if validate: | ||
_validate_transformation_matrix(transformation_matrix, rtol=rtol, atol=atol) | ||
|
||
if occupied_orbitals is None: | ||
occupied_orbitals = [] | ||
if qubit_converter is None: | ||
qubit_converter = QubitConverter(JordanWignerMapper()) | ||
|
||
n, _ = transformation_matrix.shape | ||
register = QuantumRegister(n) | ||
super().__init__(register, **circuit_kwargs) | ||
|
||
if isinstance(qubit_converter.mapper, JordanWignerMapper): | ||
operations = _prepare_fermionic_gaussian_state_jordan_wigner( | ||
register, transformation_matrix, occupied_orbitals | ||
) | ||
for gate, qubits in operations: | ||
self.append(gate, qubits) | ||
else: | ||
raise NotImplementedError( | ||
"Currently, only the Jordan-Wigner Transform is supported. " | ||
"Please use " | ||
"qiskit_nature.mappers.second_quantization.JordanWignerMapper " | ||
"to construct the qubit mapper used to construct qubit_converter." | ||
) |
Oops, something went wrong.