-
Notifications
You must be signed in to change notification settings - Fork 206
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
Improve mappers, add ModeBasedMapper #1301
Merged
mrossinek
merged 14 commits into
qiskit-community:main
from
grossardt:fix-improve-mappers-issue1289
Apr 17, 2024
Merged
Changes from 8 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
d23cb86
Implement ModeBasedMapper no caching
grossardt 3e318ba
Added caching and release note
grossardt f38cd64
Merge branch 'main' into fix-improve-mappers-issue1289
grossardt d268913
Update release note to pass spell check
grossardt 61042e0
fix typing
grossardt 1a4b2e0
fix typing for Python <3.10
grossardt ecd55eb
Merge branch 'main' into fix-improve-mappers-issue1289
grossardt 5c6f393
Merge branch 'main' into fix-improve-mappers-issue1289
woodsp-ibm 7f9f7c3
Merge branch 'main' into fix-improve-mappers-issue1289
grossardt 4477de7
suggestions by mrossinek plus changes needed to pass pylint
grossardt b1ab3c0
Update improve-mappers-b55cb0ca5fd656e4.yaml
grossardt 39a2bb2
Merge branch 'main' into fix-improve-mappers-issue1289
grossardt 466e3d8
Merge branch 'main' into fix-improve-mappers-issue1289
mrossinek 1c68e63
Merge branch 'main' into fix-improve-mappers-issue1289
mrossinek 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 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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# This code is part of a Qiskit project. | ||
# | ||
# (C) Copyright IBM 2023. | ||
# | ||
# 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. | ||
|
||
"""Mode Based Mapper.""" | ||
|
||
from __future__ import annotations | ||
|
||
from typing import Union | ||
from abc import abstractmethod | ||
|
||
import numpy as np | ||
from qiskit.quantum_info.operators import Pauli, PauliList, SparsePauliOp | ||
|
||
from qiskit_nature import QiskitNatureError | ||
from qiskit_nature.second_q.operators import SparseLabelOp | ||
from qiskit_nature.second_q.mappers.qubit_mapper import QubitMapper | ||
|
||
# Types that can be data for a SparsePauliOp | ||
PauliType = Union[PauliList, SparsePauliOp, Pauli, list, str] | ||
|
||
|
||
class ModeBasedMapper(QubitMapper): | ||
"""Mapper from ``SparseLabelOp`` to a qubit operator using a Pauli table.""" | ||
|
||
def _map_single( | ||
self, second_q_op: SparseLabelOp, *, register_length: int | None = None | ||
) -> SparsePauliOp: | ||
return self.mode_based_mapping(second_q_op, register_length=register_length) | ||
|
||
@abstractmethod | ||
def pauli_table(self, register_length: int) -> list[tuple[PauliType, PauliType]]: | ||
r"""Generates a Pauli-lookup table mapping from modes to Pauli operators or pairs of Pauli | ||
operators. | ||
|
||
This table is a list of tuples :math:`(P, Q)` of two Pauli operators, corresponding to the | ||
real part :math:`P` and imaginary part :math:`Q` for the respective mode index. These Pauli | ||
operators are used to construct the creation and annihilation operators | ||
:math:`(P \pm i Q)/2`. | ||
|
||
The generated table is processed by :meth:`.QubitMapper.sparse_pauli_operators`. | ||
grossardt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Args: | ||
register_length: the register length for which to generate the table. | ||
|
||
Returns: | ||
A list of tuples of two Pauli string operators. | ||
""" | ||
|
||
def sparse_pauli_operators( | ||
self, register_length: int | ||
) -> tuple[list[SparsePauliOp], list[SparsePauliOp]]: | ||
# pylint: disable=unused-argument | ||
"""Generates the :class:`.SparsePauliOp` terms. | ||
|
||
This uses :meth:`.QubitMapper.pauli_table` to construct a list of operators used to | ||
translate the second-quantization symbols into qubit operators. | ||
|
||
Args: | ||
register_length: the register length for which to generate the operators. | ||
|
||
Returns: | ||
Two lists stored in a tuple, consisting of the creation and annihilation operators, | ||
applied on the individual modes. | ||
""" | ||
times_creation_op = [] | ||
times_annihilation_op = [] | ||
|
||
for paulis in self.pauli_table(register_length): | ||
real_part = SparsePauliOp(paulis[0], coeffs=[0.5]) | ||
imag_part = SparsePauliOp(paulis[1], coeffs=[0.5j]) | ||
|
||
# The creation operator is given by 0.5*(X - 1j*Y) | ||
creation_op = real_part - imag_part | ||
times_creation_op.append(creation_op) | ||
|
||
# The annihilation operator is given by 0.5*(X + 1j*Y) | ||
annihilation_op = real_part + imag_part | ||
times_annihilation_op.append(annihilation_op) | ||
|
||
return (times_creation_op, times_annihilation_op) | ||
|
||
def mode_based_mapping( | ||
self, | ||
second_q_op: SparseLabelOp, | ||
register_length: int | None = None, | ||
) -> SparsePauliOp: | ||
# pylint: disable=unused-argument | ||
"""Utility method to map a ``SparseLabelOp`` to a qubit operator using a pauli table. | ||
|
||
Args: | ||
second_q_op: the `SparseLabelOp` to be mapped. | ||
register_length: when provided, this will be used to overwrite the ``register_length`` | ||
attribute of the operator being mapped. This is possible because the | ||
``register_length`` is considered a lower bound. | ||
|
||
Returns: | ||
The qubit operator corresponding to the problem-Hamiltonian in the qubit space. | ||
|
||
Raises: | ||
QiskitNatureError: If number length of pauli table does not match the number | ||
of operator modes, or if the operator has unexpected label content | ||
""" | ||
if register_length is None: | ||
register_length = second_q_op.register_length | ||
|
||
times_creation_op, times_annihilation_op = self.sparse_pauli_operators(register_length) | ||
|
||
# make sure ret_op_list is not empty by including a zero op | ||
ret_op_list = [SparsePauliOp("I" * register_length, coeffs=[0])] | ||
|
||
for terms, coeff in second_q_op.terms(): | ||
# 1. Initialize an operator list with the identity scaled by the `coeff` | ||
ret_op = SparsePauliOp("I" * register_length, coeffs=np.array([coeff])) | ||
|
||
# Go through the label and replace the fermion operators by their qubit-equivalent, then | ||
# save the respective Pauli string in the pauli_str list. | ||
for term in terms: | ||
char = term[0] | ||
if char == "": | ||
break | ||
position = int(term[1]) | ||
if char == "+": | ||
ret_op = ret_op.compose(times_creation_op[position], front=True).simplify() | ||
elif char == "-": | ||
ret_op = ret_op.compose(times_annihilation_op[position], front=True).simplify() | ||
# catch any disallowed labels | ||
else: | ||
raise QiskitNatureError( | ||
f"FermionicOp label included '{char}'. Allowed characters: I, N, E, +, -" | ||
) | ||
ret_op_list.append(ret_op) | ||
|
||
sparse_op = SparsePauliOp.sum(ret_op_list).simplify() | ||
return sparse_op |
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why this is necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this because otherwise mypy fails due to this issue: python/mypy#7509