Skip to content
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

Add PolynomialTensor class #756

Merged
merged 36 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
65b173f
adding PolynomialTensor class
SaashaJoshi Jul 20, 2022
71c3591
adding unittest corresponding PolynomialTensor class; making changes …
SaashaJoshi Jul 21, 2022
91d1f89
adding conjugate and transpose functions
SaashaJoshi Jul 21, 2022
5d09484
made changes to polynomial_tensor and test_polyomial_tensor files
SaashaJoshi Aug 2, 2022
788ae81
Merge branch 'main' into poly_tensor
manoelmarques Aug 2, 2022
679d340
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Aug 8, 2022
230a4f4
Merge branch 'main' into poly_tensor
manoelmarques Aug 8, 2022
7b38cc6
Merge branch 'Qiskit:main' into poly_tensor
SaashaJoshi Aug 8, 2022
d08e297
Merge "main" into poly_tensor
SaashaJoshi Aug 10, 2022
2d32bf8
updating polynomial_tensor and unittest
SaashaJoshi Aug 10, 2022
3f15fc0
Merge branch 'Qiskit:main' into poly_tensor
SaashaJoshi Aug 11, 2022
0d275e6
updating polynomial tensor and unittest
SaashaJoshi Aug 11, 2022
c84f5d2
Merge branch 'Qiskit:main' into poly_tensor
SaashaJoshi Aug 12, 2022
5b771b2
update unittest
SaashaJoshi Aug 12, 2022
92e6857
Merge branch 'Qiskit/main' into poly_tensor
SaashaJoshi Aug 23, 2022
326ac9b
updating polynomial_tensor file
SaashaJoshi Aug 23, 2022
034de66
Merge branch 'Qiskit/main' into poly_tensor
SaashaJoshi Sep 1, 2022
8bdfefc
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 1, 2022
094c6ef
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 1, 2022
4273205
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 1, 2022
497ae60
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 1, 2022
63f9ef1
Merge branch 'Qiskit/main' into poly_tensor
SaashaJoshi Sep 4, 2022
ab551e9
update polynomial_tensor and test_polynomial_tensor
SaashaJoshi Sep 4, 2022
7018443
Merge branch 'Qiskit/main' into poly_tensor
SaashaJoshi Sep 6, 2022
5c9d00b
adding register_length to polynomial tensor
SaashaJoshi Sep 6, 2022
5313c21
Merge remote-tracking branch 'upstream/main' into poly_tensor
SaashaJoshi Sep 7, 2022
0371db1
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 7, 2022
0e5c3f7
Merge branch 'main' into poly_tensor
woodsp-ibm Sep 12, 2022
01b8d50
changes to polynomial_tensor - adding register_length
SaashaJoshi Sep 12, 2022
468a1c3
adding equiv method to polynomial_tensor. adding unittests for dunders
SaashaJoshi Sep 13, 2022
5ab41ee
lint and mypy update
SaashaJoshi Sep 13, 2022
807eb1a
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 13, 2022
db03648
updating polynomial_tensor
SaashaJoshi Sep 13, 2022
7619b15
Update qiskit_nature/second_q/operators/polynomial_tensor.py
SaashaJoshi Sep 13, 2022
8344b60
update polynomial_tensor
SaashaJoshi Sep 13, 2022
c765c72
Merge branch 'main' into poly_tensor
mrossinek Sep 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pylintdict
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ physrevd
physik
plesset
pmatrix
polynomialtensor
polypeptides
popovas
pos
Expand Down
3 changes: 3 additions & 0 deletions qiskit_nature/second_q/operators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,21 @@
SpinOp
SecondQuantizedOp
VibrationalOp
PolynomialTensor
"""

from .fermionic_op import FermionicOp
from .second_quantized_op import SecondQuantizedOp
from .spin_op import SpinOp
from .vibrational_op import VibrationalOp
from .polynomial_tensor import PolynomialTensor
from .sparse_label_op import SparseLabelOp

__all__ = [
"FermionicOp",
"SecondQuantizedOp",
"SpinOp",
"VibrationalOp",
"PolynomialTensor",
"SparseLabelOp",
]
208 changes: 208 additions & 0 deletions qiskit_nature/second_q/operators/polynomial_tensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# 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.

"""PolynomialTensor class"""

from __future__ import annotations
from typing import Dict, Iterator
from collections.abc import Mapping
from numbers import Number
import numpy as np
from qiskit.quantum_info.operators.mixins import (
LinearMixin,
AdjointMixin,
TolerancesMixin,
)


class PolynomialTensor(LinearMixin, AdjointMixin, TolerancesMixin, Mapping):
"""PolynomialTensor class"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a future reviewer: I will flesh out this docstring in an upcoming PR when working on #666 👍


def __init__(self, data: Mapping[str, np.ndarray | Number], register_length: int) -> None:
"""
Args:
data: mapping of string-based operator keys to coefficient matrix values.
register_length: dimensions of the value matrices in data mapping.
Raises:
ValueError: when length of operator key does not match dimensions of value matrix.
ValueError: when value matrix does not have consistent dimensions.
ValueError: when some or all value matrices in ``data`` have different dimensions.
"""
copy_dict: Dict[str, np.ndarray] = {}

for key, value in data.items():
if isinstance(value, Number):
value = np.asarray(value)

if len(value.shape) != len(key):
raise ValueError(
f"Data key {key} of length {len(key)} does not match "
f"data value matrix of dimensions {value.shape}"
)

dims = set(value.shape)

if len(dims) > 1:
raise ValueError(
f"For key {key}: dimensions of value matrix are not identical {value.shape}"
)
if len(dims) == 1 and dims.pop() != register_length:
raise ValueError(
f"Dimensions of value matrices in data dictionary do not match the provided "
f"register length, {register_length}"
)

copy_dict[key] = value

self._data = copy_dict
self._register_length = register_length

@property
def register_length(self) -> int:
"""Returns register length of the operator key in `PolynomialTensor`."""
return self._register_length

def __getitem__(self, __k: str) -> (np.ndarray | Number):
"""
Returns value matrix in the `PolynomialTensor`.

Args:
__k: operator key string in the `PolynomialTensor`.
Returns:
Value matrix corresponding to the operator key `__k`
"""
return self._data.__getitem__(__k)

def __len__(self) -> int:
"""
Returns length of `PolynomialTensor`.
"""
return self._data.__len__()

def __iter__(self) -> Iterator[str]:
"""
Returns iterator of the `PolynomialTensor`.
"""
return self._data.__iter__()

def _multiply(self, other: complex) -> PolynomialTensor:
"""Scalar multiplication of PolynomialTensor with complex

Args:
other: scalar to be multiplied with the ``PolynomialTensor``.
Returns:
the new ``PolynomialTensor`` product object.
Raises:
TypeError: if ``other`` is not a ``Number``.
"""
if not isinstance(other, Number):
raise TypeError(f"other {other} must be a number")

prod_dict: Dict[str, np.ndarray] = {}
for key, matrix in self._data.items():
prod_dict[key] = np.multiply(matrix, other)
return PolynomialTensor(prod_dict, self._register_length)

def _add(self, other: PolynomialTensor, qargs=None) -> PolynomialTensor:
"""Addition of PolynomialTensors

Args:
other: second``PolynomialTensor`` object to be added to the first.
Returns:
the new summed ``PolynomialTensor``.
Raises:
TypeError: when ``other`` is not a ``PolynomialTensor``.
ValueError: when values corresponding to keys in ``other`` and
the first ``PolynomialTensor`` object do not match.
"""
if not isinstance(other, PolynomialTensor):
raise TypeError("Incorrect argument type: other should be PolynomialTensor")

if self._register_length != other._register_length:
raise ValueError(
"The dimensions of the PolynomialTensors which are to be added together, do not "
f"match: {self._register_length} != {other._register_length}"
)

sum_dict = {key: value + other._data.get(key, 0) for key, value in self._data.items()}
other_unique = {key: other._data[key] for key in other._data.keys() - self._data.keys()}
sum_dict.update(other_unique)

return PolynomialTensor(sum_dict, self._register_length)

def __eq__(self, other: object) -> bool:
"""Check equality of first PolynomialTensor with other

Args:
other: second``PolynomialTensor`` object to be compared with the first.
Returns:
True when ``PolynomialTensor`` objects are equal, False when unequal.
"""
if not isinstance(other, PolynomialTensor):
return False

if self._register_length != other._register_length:
return False

if self._data.keys() != other._data.keys():
return False

for key, value in self._data.items():
if not np.array_equal(value, other._data[key]):
return False
return True

def equiv(self, other: object) -> bool:
"""Check equivalence of first PolynomialTensor with other

Args:
other: second``PolynomialTensor`` object to be compared with the first.
Returns:
True when ``PolynomialTensor`` objects are equivalent, False when not.
"""
if not isinstance(other, PolynomialTensor):
return False

if self._register_length != other._register_length:
return False

if self._data.keys() != other._data.keys():
return False

for key, value in self._data.items():
if not np.allclose(value, other._data[key], atol=self.atol, rtol=self.rtol):
return False
return True

def conjugate(self) -> PolynomialTensor:
"""Conjugate of PolynomialTensors

Returns:
the complex conjugate of the ``PolynomialTensor``.
"""
conj_dict: Dict[str, np.ndarray] = {}
for key, value in self._data.items():
conj_dict[key] = np.conjugate(value)

return PolynomialTensor(conj_dict, self._register_length)

def transpose(self) -> PolynomialTensor:
"""Transpose of PolynomialTensor

Returns:
the transpose of the ``PolynomialTensor``.
"""
transpose_dict: Dict[str, np.ndarray] = {}
for key, value in self._data.items():
transpose_dict[key] = np.transpose(value)

return PolynomialTensor(transpose_dict, self._register_length)
Loading