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

ENH: Add np.linalg.matrix_transpose #22767

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

Closed
wants to merge 1 commit into from

Conversation

asmeurer
Copy link
Member

@asmeurer asmeurer commented Dec 10, 2022

Unlike np.transpose(), matrix_transpose() only operates on the last 2 dimensions of an array, and raises an exception if it is 0- or 1-dimensional.

This is a function from the array API specification. See https://data-apis.org/array-api/latest/API_specification/generated/signatures.linear_algebra_functions.matrix_transpose.html

This was mentioned in this issue #13797

Some things left to do, which I would like some help with:

  • matrix_transpose should also be added to the main np namespace. What is the correct way to do that? (the spec specifies it should be in both the main namespace and the linalg sub-namespace)
  • I need to add it to the documentation (presumably under its main namespace name, which is why I will do this once I have the above item done)
  • There is also an mT attribute that can be added to the array object, which is a shorthand for matrix_transpose. Should I add that in this PR? There was some discussion on the list about it, which is why I haven't done it yet.
  • This replaces the internal np.linalg.linalg.transpose function. Should I re-include that function for backwards compatibility?
  • Did I implement everything correctly here? I added the @array_function_dispatch to the function? Is there anything else I need to do?
  • Is it OK that this function is implemented in pure Python? It is basically a wrapper around np.swapaxes(x, -1, -2) (with a shape check to give a better error message for ndim < 2)
  • Is the error message and error type (ValueError) OK for ndim < 2?
  • I also know I need to add a release note entry. I will do so once we sort out what will happen here for np.matrix_transpose and ndarry.mT.
  • Is it OK to use a positional-only argument for this function? There shouldn't be a problem adding it for a new function, but we can also wait until we generally move all functions to positional-only.

Unlike np.transpose(), matrix_transpose() only operates on the last 2
dimensions of an array, and raises an exception if it is 0- or 1-dimensional.

This is a function from the array API specification. See https://data-apis.org/array-api/latest/API_specification/generated/signatures.linear_algebra_functions.matrix_transpose.html
@charris
Copy link
Member

charris commented Dec 11, 2022

LGTM on first look, needs a release note.

Is there a particular reason for the name "matrix_transpose"? Something shorter would be nice, but the current name has the advantage of being unambiguous. What about a method, "mT"? I would be in favor of such an addition despite the hesitance to add new methods.

@asmeurer
Copy link
Member Author

Is there a particular reason for the name "matrix_transpose"? Something shorter would be nice, but the current name has the advantage of being unambiguous.

That's the idea. Ideally just transpose and .T would do a matrix transpose, but currently they don't for stacked matrices. Changing that is a difficult proposition, hence the new, unambiguous function.

What about a method, "mT"?

A mT attribute (not method) is proposed, but it is a bit more controversial, so I will likely implement in a separate pull request.

@seberg seberg added 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes 62 - Python API Changes or additions to the Python API. Mailing list should usually be notified. labels Dec 20, 2022
Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

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

LGTM, it sounds like nobody minded the addition. The only thing is whether we should coerce, since NumPy does that everywhere (this does not affect the internal usage in linalg).
If we don't coerce, the function has little to add over an attribute?

def _matrix_transpose_dispatcher(a):
return (a,)

@array_function_dispatch(_matrix_transpose_dispatcher)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@array_function_dispatch(_matrix_transpose_dispatcher)
@array_function_dispatch(_matrix_transpose_dispatcher, module='numpy.linalg')

although I guess you want to copy it also into the main namespace, in which case we have to decide for one of the two modules.

"""
if a.ndim < 2:
Copy link
Member

Choose a reason for hiding this comment

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

Hmmm, this will effectively not work for many array-likes, which is fairly untypical for NumPy. Is that what we want? swapaxes itself checks for the attribute or coerces unfortunately.

Copy link
Member

Choose a reason for hiding this comment

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

If we implement .mT then this function should possibly just try obj.mT and otherwise coerce?

a = np.array([[[1, 2], [3, 4]], [[-1, -2], [-3, -4]]])
aT = np.array([[[1, 3], [2, 4]], [[-1, -3], [-2, -4]]])
assert_array_equal(matrix_transpose(a), aT)
assert_array_equal(matrix_transpose(aT), a)
Copy link
Member

Choose a reason for hiding this comment

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

Could also check for may_share_memory() or a.base is a just for completeness sake.

@seberg
Copy link
Member

seberg commented Dec 20, 2022

To answer a few questions:

  1. ValueError seems right, we have AxisError, but it subclasses ValueError and I doubt this normally runs into an other error currently.
  2. I am OK with removing np.linalg.linalg.transpose, but be ready to re-add it if downstream complains (possibly with a deprecation warning).
  3. If you plan to add .mT anyway, that might make things simpler here, since it should probably be used here.
  4. I like using positional-only in such clear-cut cases, but don't care either way. I expect we could get away with transitioning most of these type of functions anyway.

@rgommers
Copy link
Member

rgommers commented Jan 4, 2024

This was superseded by gh-25155 I think, we've got a matrix_transpose in the main namespace and in linalg. Can this be closed?

@rgommers rgommers closed this Jan 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
01 - Enhancement 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes 62 - Python API Changes or additions to the Python API. Mailing list should usually be notified. component: numpy.linalg
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants