Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

API: Add matrix_norm, vector_norm, vecdot and matrix_transpose [Array API] #25155

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

Merged
merged 1 commit into from
Dec 14, 2023

Conversation

mtsokol
Copy link
Member

@mtsokol mtsokol commented Nov 15, 2023

Hi @rgommers @ngoldbaum,

This PR contains the last Array API compatibility update for numpy.linalg. It adds:

  • numpy.linalg.matrix_norm
  • numpy.linalg.vector_norm
  • numpy.vecdot and numpy.linalg.vecdot
  • numpy.matrix_transpose and numpy.linalg.matrix_transpose

@ngoldbaum
Copy link
Member

The mypy failure is real, I restarted the cygwin job.

Copy link
Member

@ngoldbaum ngoldbaum left a comment

Choose a reason for hiding this comment

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

Overall looks good, tests just need to be cleaned up. I see that the implementations are copy/pasted from the existing array API wrappers. This is probably fine as a first pass but I suspect there are more performant implementations we could use.


* `numpy.vecdot` and `numpy.linalg.vecdot`

* `numpy.matrix_transpose` and `numpy.linalg.matrix_transpose`
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a sentence or two describing what these functions do?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure! I added one sentence descriptions from Array API definitions.

@mtsokol mtsokol force-pushed the array-api-linalg branch 5 times, most recently from 8102ddb to 665d6c6 Compare December 8, 2023 14:18
@charris charris changed the title API: Add matrix_norm, vector_norm, vecdot and matrix_transpose [Array API] API: Add matrix_norm, vector_norm, vecdot and matrix_transpose [Array API] Dec 8, 2023
transpose : Generic transpose method.

"""
x = asarray(x)
Copy link
Member

@ngoldbaum ngoldbaum Dec 8, 2023

Choose a reason for hiding this comment

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

Similar to the discussion in the other PR - should this be asanyarray?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think there was roughly an agreement in #25101 (comment) that asanyarray can be used in place of asarray.

I replaced it for functions added here and outer that has been merged.

@mtsokol mtsokol force-pushed the array-api-linalg branch 2 times, most recently from b3011a7 to daa0350 Compare December 11, 2023 18:13
x1_ = np.moveaxis(x1_, axis, -1)
x2_ = np.moveaxis(x2_, axis, -1)

res = x1_[..., None, :] @ x2_[..., None]
Copy link
Member

Choose a reason for hiding this comment

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

@seberg mentioned on the triage call today that this is supposed to do the hermitian conjugate according to the array API standard - does the matmul operator do that?

Copy link
Member

Choose a reason for hiding this comment

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

And if so, probably worth adding a test that has complex vectors.

Copy link
Member Author

@mtsokol mtsokol Dec 14, 2023

Choose a reason for hiding this comment

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

Right, a conjugate was missing - I added it (and a test) according to Array API.

Note: np.vdot does conjugate on the first parameter (if it's complex), where np.vecdot does it on the second one (I mentioned it in the vecdot's docs).

Copy link
Member

Choose a reason for hiding this comment

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

no, the numpy way is correct, the array-api way is just a bug.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, right (I see that pytorch also performs conjugate on the first argument). Let me change that here and fix it in the Array API.

Copy link
Member

Choose a reason for hiding this comment

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

Can you open an issue that this should have a dedicated ufunc? BLAS should have kernels which perform the complex conjugation on the fly, so at least for the complex conjugating case, this is really not ideal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Note that wikipedia disagrees: the conjugate of the second argument is taken: https://en.wikipedia.org/wiki/Dot_product#Complex_vectors

Copy link
Member

Choose a reason for hiding this comment

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

Mathematicians and physicists have opposite conventions. Mathematicians use sesquilinear forms, physicists follow the Dirac bracket convention (I don't know who actually started the convention). It can make teaching awkward ...

Copy link
Contributor

Choose a reason for hiding this comment

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

@ngoldbaum
Copy link
Member

Alright, let's pull this one in. Thanks @mtsokol!

One note: in the release notes the code literals should be wrapped in double backticks, not single backticks. Can you go through all the release notes you've added and make sure they're all formatted correctly? Merging this anyway since that's a minor issue that can be fixed separately.

@ngoldbaum ngoldbaum merged commit 8162caf into numpy:main Dec 14, 2023
@mtsokol mtsokol deleted the array-api-linalg branch December 14, 2023 16:05
@mtsokol
Copy link
Member Author

mtsokol commented Dec 14, 2023

One note: in the release notes the code literals should be wrapped in double backticks, not single backticks. Can you go through all the release notes you've added and make sure they're all formatted correctly? Merging this anyway since that's a minor issue that can be fixed separately.

@ngoldbaum I did this formatting on purpose. Double backticks give code format, where single backticks create a link to NumPy member's documentation.

For example see: https://github.com/numpy/numpy/blob/4b5ae68c78a222eba2e07cc1e34bd29d5cfeb30d/doc/release/upcoming_changes/22539.deprecation.rst?plain=1 from a PR shipped with 1.25.0 release.

which resulted in:

image

@ngoldbaum
Copy link
Member

Ah, thanks for the explanation! Gotta love sphinx/rst trivia like that.

f"but they are: {x1_shape[axis]} and {x2_shape[axis]}."
)

x1_, x2_ = np.broadcast_arrays(x1, x2)
Copy link
Contributor

Choose a reason for hiding this comment

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

Darn, another one. Would it still be possible to add subok=True here to allow subclasses to "just work"?

ndim = builtins.max(x1.ndim, x2.ndim)
x1_shape = (1,)*(ndim - x1.ndim) + tuple(x1.shape)
x2_shape = (1,)*(ndim - x2.ndim) + tuple(x2.shape)
if x1_shape[axis] != x2_shape[axis]:
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this use of axis is contrary to how a gufunc would interpret it: there axis is taken for every element separately before broadcasting, i.e., for vectors with shapes (3, 4) and (3, 2, 4) and axis=0, the output would have shape (2, 4). You can see this from

from numpy._core.umath_tests import inner1d

a = np.arange(12).reshape(3, 4)
b = np.arange(24).reshape(3, 2, 4)

inner1d(a, b, axis=0).shape
# (2, 4)

I think we should stick with this, otherwise this is going to be very confusing in the future (alternatively, one would need to change how axis and axes are interpreted in gufuncs...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants