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

Adds pinv to tensorflow backend (https://github.com/google/TensorNetwork/issues/844) #935

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions tensornetwork/backends/tensorflow/tensorflow_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,26 @@ def eps(self, dtype: Type[np.number]) -> float:
float: Machine epsilon.
"""
return tf.experimental.numpy.finfo(dtype).eps

def pinv(self, tensor: Tensor, rcond: float = 1E-15, hermitian: bool = False) -> Tensor:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can remove the hermitian argument

Copy link
Author

Choose a reason for hiding this comment

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

I had included it as it was an argument for numpy. I'll remove it in the next commit.
Thanks for the review!

"""
Compute the Moore-Penrose/Pseudo inverse of a tensor.

Args:
tensor: A tensor.
rcond: Cutoff for small singular values
hermitian: If True, matrix provided in function argument is assumed to be
Hermitian (symmetric if real-valued)
This argument is not supported in the TensorFlow
backend and an error will be raised if it is
specified.

Returns:
tensor: The pseudo inverse of `tensor`
"""
if hermitian != False:
errstr = (f"hermitian = {hermitian} must be False (the default)"
f"with TensorFlow backend.")
raise NotImplementedError(errstr)

return tf.linalg.pinv(tensor, rcond=rcond)
12 changes: 12 additions & 0 deletions tensornetwork/backends/tensorflow/tensorflow_backend_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,3 +629,15 @@ def test_power(dtype):
def test_eps(dtype):
backend = tensorflow_backend.TensorFlowBackend()
assert backend.eps(dtype) == tf.experimental.numpy.finfo(dtype).eps

def test_pinv():
backend = tensorflow_backend.TensorFlowBackend()
np.random.seed(10)
tensor = np.random.rand(2, 3, 4)
rcond = np.random.rand(1)[0] * 1E-14
expected = tf.linalg.pinv(tensor, rcond)
actual = backend.pinv(tensor, rcond)
np.testing.assert_allclose(expected, actual)
expected = tf.linalg.pinv(tensor)
actual = backend.pinv(tensor)
np.testing.assert_allclose(expected, actual)
Copy link
Collaborator

Choose a reason for hiding this comment

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

add a test that actual @ tensor and tensor @ actual equal the identity (within the desired error)

Copy link
Author

Choose a reason for hiding this comment

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

Would testing for all the criteria in https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse be a better test? (As for an example given in tf's documentation, the product wasn't identity)