-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Added an 'elementary' function. #4573
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
Changes from 1 commit
f9cb6cb
159b9ae
0e10a44
e4e3ca1
c3f45d3
9dba261
1da28fd
4de601b
08965f5
480c51b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -998,3 +998,119 @@ def triu_indices_from(arr, k=0): | |
if arr.ndim != 2: | ||
raise ValueError("input array must be 2-d") | ||
return triu_indices(arr.shape[-2], k=k, m=arr.shape[-1]) | ||
|
||
|
||
def elementary(N, i, j=None, t=None, dtype=float): | ||
""" | ||
Return an array arranged like an elementary matrix. | ||
|
||
Parameters | ||
---------- | ||
N : int | ||
The size of the NxN array to be returned. Elementary matrices | ||
are be square. | ||
i : int | ||
The index of the first row on which operations are to be | ||
performed. | ||
j : int | ||
If set, the index of the second row on which operations are to | ||
be performed. | ||
t : scalar | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, I'd go for more descriptive parameter names. Maybe |
||
If set, the factor by which a given row will be multiplied. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason not to document the dtype arg? |
||
Returns | ||
------- | ||
m : ndarray of shape (NxN) | ||
An identity array that has had a single row operation performed | ||
on it. | ||
|
||
See also | ||
-------- | ||
eye, identity | ||
|
||
Examples | ||
------- | ||
To swap the the first and third rows of a 4x4 identity matirx: | ||
|
||
>>> L = elementary(4, 0, 2) | ||
>>> L | ||
array([[ 0., 0., 1., 0.], | ||
[ 0., 1., 0., 0.], | ||
[ 1., 0., 0., 0.], | ||
[ 0., 0., 0., 1.]]) | ||
|
||
When the elementary array is multiplied by a given matrix, the | ||
result is the matrix with its first and third rows swapped. | ||
|
||
>>> H = np.matrix([[ 2, 3, 5, 7], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is that? Link, please? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what the official link is, but the
8000
re's precedent here: scipy/scipy#3516 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not a NumPy or SciPy core dev and I haven't seen any definitive decision, but I'll cite @njsmith in PEP 465 (#4351):
which I wholeheartedly second. Arrays should be preferred because they are more flexible, and when arrays are used, using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function's main usefulness is in the case of matrix multiplication. I can't think of any good uses for elementary() without matrix multiplication. I've added a note to the documentation clarifying that. Also an example I chose for my documentation makes clear what happens in A * B when one of A, B is an array and the other a matrix, but I take your point, that it can be confusing. Until PEP 465 gets accepted, is there a better way to do matrix multiplication than np.matrix? Should I write documentation assuming that PEP 465 has already been incorporated? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With arrays, the multiplication is written There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, awesome. Thanks. |
||
[11, 13, 17, 19], | ||
[23, 29, 31, 37], | ||
[41, 43, 47, 53]]) | ||
>>> L*H | ||
matrix([[ 23., 29., 31., 37.], | ||
[ 11., 13., 17., 19.], | ||
[ 2., 3., 5., 7.], | ||
[ 41., 43., 47., 53.]]) | ||
|
||
If the matrix is multiplied by the elementary array (i.e., the | ||
multiplication takes place in reverse order), the result is the | ||
given matrix with its first and third columns swapped. | ||
|
||
>>> H*L | ||
matrix([[ 5., 3., 2., 7.], | ||
[ 17., 13., 11., 19.], | ||
[ 31., 29., 23., 37.], | ||
[ 47., 43., 41., 53.]]) | ||
|
||
To add a multiple of a matrix's second row to the same matrix's | ||
fourth row: | ||
|
||
>>> H | ||
matrix([[ 2, 3, 5, 7], | ||
[11, 13, 17, 19], | ||
[23, 29, 31, 37], | ||
[41, 43, 47, 53]]) | ||
>> M=elementary(4, 1, 3, 10000, int) | ||
>> M | ||
array([[ 1, 0, 0, 0], | ||
[ 0, 1, 0, 0], | ||
[ 0, 0, 1, 0], | ||
[ 0, 10000, 0, 1]]) | ||
>> M*H | ||
matrix([[ 2, 3, 5, 7], | ||
[ 11, 13, 17, 19], | ||
[ 23, 29, 31, 37], | ||
[110041, 130043, 170047, 190053]]) | ||
|
||
To multiply only the last column of a matrix by a scalar: | ||
|
||
>>> H | ||
matrix([[ 2, 3, 5, 7], | ||
[11, 13, 17, 19], | ||
[23, 29, 31, 37], | ||
[41, 43, 47, 53]]) | ||
>>> H*elementary(len(H), len(H)-1, t=2) | ||
matrix([[ 2., 3., 5., 14.], | ||
[ 11., 13., 17., 38.], | ||
[ 23., 29., 31., 74.], | ||
[ 41., 43., 47., 106.]]) | ||
|
||
Any nonsingular matrix can be formed by taking the product of an array | ||
of elementary matrices. | ||
|
||
""" | ||
m=eye(N, dtype=dtype) | ||
if j==None and t==None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PEP8 wants spaces around operators. Also checking for |
||
raise ValueError("One or more of {0} and {1} must be set.".format( \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the format really required here? You're interpolating string literals. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @larsmans Good point. |
||
'j', 't')) | ||
elif t==None: | ||
swap = array(m[i]) | ||
m[i] = m[j] | ||
m[j] = swap | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, right. But what about |
||
return m | ||
elif j==None: | ||
m[i] *= t | ||
return m | ||
else: | ||
m[j] += (t * m[i]) | ||
return m |
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.
"are square by definition", perhaps?