In MATLAB you can compute the Jordan normal form of a matrix by using the the function jordan.
It there an equivalent function available in NumPy and SciPy?
The MATLAB jordan function is from the Symbolic Math Toolbox, so it does not seem unreasonable to get its Python replacement from the SymPy library. Specifically, the Matrix class has the method jordan_form. You can pass a numpy array as an argument when you create a sympy Matrix. For example, the following is from the wikipedia article on the Jordan normal form:
In [1]: import numpy as np
In [2]: from sympy import Matrix
In [3]: a = np.array([[5, 4, 2, 1], [0, 1, -1, -1], [-1, -1, 3, 0], [1, 1, -1, 2]])
In [4]: m = Matrix(a)
In [5]: m
Out[5]:
Matrix([
[ 5, 4, 2, 1],
[ 0, 1, -1, -1],
[-1, -1, 3, 0],
[ 1, 1, -1, 2]])
In [6]: P, J = m.jordan_form()
In [7]: J
Out[7]:
Matrix([
[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 4, 1],
[0, 0, 0, 4]])
There's this implementation.
It will definitely not be as fast as MATLAB, though.
Related
If I do
from sympy import *
from sympy.physics.quantum import TensorProduct
m = Matrix([[0,1],[0,0]])
TensorProduct(m,m)
I get
Matrix([
[0, 0, 0, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
which is the correct result.
However, if I try
TensorProduct(conjugate(m),m)
I get
Matrix([
[0, 1],
[0, 0]])xMatrix([
[0, 1],
[0, 0]])
why does the conjugate function "force" the TensorProduct function to considerate conjugate(m) in an abstract way? Can anyone explain what is going on?
I currently have a two-dimensional numpy array of shape (m, n). Furthermore, I have two (m, p) arrays of indices i1 and i2. The indices are always contiguous!
import numpy as np
t = np.array([[-1, -1, 0, 0, 1, 2, 2],
[-1, -1, 0, 1, 2, 3, 3],
[0, 0, 1, 2, 2, 3, 3]])
i1 = np.array([3, 2, 2])
i2 = np.array([4, 3, 3])
How do I use the arrays i1 and i2 to slice t in order to obtain the following sub-matrix?
expected_t = np.array([
[0, 1],
[0, 1],
[1, 2]
])
That is
expected_t[0, :] = t[0, i1[0]:i2[0]]
expected_t[1, :] = t[1, i1[1]:i2[1]]
expected_t[2, :] = t[2, i1[2]:i2[2]]
Furthermore, is this possible to do without copying the data by creating a view?
Thanks in advance for all help!
Use fancy indexing in numpy:
t[np.arange(3).reshape(3,1), np.vstack((i1,i2)).T]
OR
t[np.arange(3), np.vstack((i1,i2))].T
Both will have the result:
array([[0, 1],
[0, 1],
[1, 2]])
I suggest this, but I don't know if it exists a fastest way of indexing following the example :
import numpy as np
t = np.array([[-1, -1, 0, 0, 1, 2, 2],
[-1, -1, 0, 1, 2, 3, 3],
[0, 0, 1, 2, 2, 3, 3]])
i1 = np.array([3, 2, 2])
i2 = np.array([4, 3, 3])
output = []
for i, (min_, max_) in enumerate(zip(i1, i2)):
output.append(t[i, min_:max_+1])
expected_t = np.array(output)
Or shorter :
expected_t = np.array([t[i, j:k+1] for (i,j,k) in zip(range(len(t)), i1, i2)])
Is there a way with Python to perform circular convolution between two 1D arrays,
like with Matlab function cconv?
I tried numpy.convolve but it isn't the same, and I can’t find an equivalent.
You can try this command : scipy.ndimage.filters.convolve1d
You have an option which is named modeand you can write mode = wrap
With that, you get periodic boundary conditions as padding for the convolution
For example :
result = scipy.ndimage.convolve(image,kernel,mode='wrap')
import numpy as np
image = np.array([[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 0, 0]])
kernel = np.array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
from scipy.ndimage import convolve
convolve(image, kernel, mode='wrap')
array([[1, 0, 1, 1],
[1, 0, 1, 1],
[1, 0, 1, 1]])
I am trying to extract all the indexes from an (N x N x N) numpy array, where values in both A and B arrays are equal to some value x - find the common overlap.
I am trying:
A[A==1 and B==1]
but get an error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
How do I get around this?
Numpy cannot overload the "and" keyword. However it overloads the binary AND operator & for this. Try:
A[(A==1) & (B==1)]
The parantheses are important. I find it often (not always)better readable then logical_and
A == 1 and B == 1 are boolean arrays, while (A==1)*(B==1) is an array of integers. You can find the nonzero entries of this array through NumPy's where:
np.where((A==1)*(B==1))
Demo
Consider the following 3-dimensional arrays, which are randomly populated with values -1, 0 and 1:
In [1066]: import numpy as np
In [1067]: np.random.seed(2016) # this is to get the same results on multiple runs
In [1068]: N = 3
...: A = np.random.randint(low=-1, high=2, size=(N, N, N))
...: B = np.random.randint(low=-1, high=2, size=(N, N, N))
In [1069]: A
Out[1069]:
array([[[ 1, 1, 0],
[-1, 1, -1],
[-1, -1, -1]],
[[ 0, 1, 1],
[-1, 1, 1],
[ 0, 1, 0]],
[[ 0, 1, 0],
[-1, 1, 1],
[-1, 1, 0]]])
In [1070]: B
Out[1070]:
array([[[-1, 0, 0],
[-1, -1, 1],
[ 0, -1, -1]],
[[-1, -1, -1],
[-1, 1, 1],
[-1, 1, 1]],
[[ 1, 1, -1],
[-1, 0, 1],
[-1, 1, -1]]])
The function where returns a tuple of integer arrays which triggers advanced indexing:
In [1071]: idx = np.where((A==1)*(B==1))
In [1072]: idx
Out[1072]:
(array([1, 1, 1, 2, 2, 2], dtype=int64),
array([1, 1, 2, 0, 1, 2], dtype=int64),
array([1, 2, 1, 1, 2, 1], dtype=int64))
In [1073]: A[idx]
Out[1073]: array([1, 1, 1, 1, 1, 1])
In [1074]: B[idx]
Out[1074]: array([1, 1, 1, 1, 1, 1])
perhaps slightly hasty posting this question. Used numpy's
logical_and(x1, x2[, out])
in the end which did the job perfectly!
I have a 5x5 array of arrays and I'm trying to matrix multiply the transpose of one row with another row.
import numpy as np
a = np.array([1, 4, 6, 4, 1])
b = np.array([-1, -2, 0, 2, 1])
c = np.array([-1, 2, 0, -2, 1])
d = np.array([-1, 0, 2, 0, -1])
e = np.array([1, -4, 6, -4, 1])
f = np.vstack([a, b, c, d, e])
result = np.dot(f[1, :].T, f[1, :])
I assumed this would work but apparently
f[1, :].T
ends up becoming
[-1, -2, 0, 2, 1]
rather than
[[-1]
[-2]
[ 0]
[ 2]
[ 1]]
and so np.dot treats it like a real dot product rather than doing matrix multiplication.
I found out that list slicing where one index is an integer and all others are :s reduces the dimension by one so so the shape of f[1, :] is not (1, 5) but (5,) and so transposing it does nothing.
I've been able to get it to working using f[1, :].reshape((1, 5)) but is there a better way of doing this? Am I missing a simple way of getting the transpose without having to reshape it?
You can use np.newaxis to add a dimension when slicing, to compensate for the dimension that is otherwise lost.
f[1, :, np.newaxis]
produces the single-column 2D array you want. Putting np.newaxis before the colon would give a single-row 2D array.
For numpy arrays it is often favorable to have this behavior, to circumvent this you can always use the numpy matrix class.
>>> f = np.matrix(f)
>>> f
matrix([[ 1, 4, 6, 4, 1],
[-1, -2, 0, 2, 1],
[-1, 2, 0, -2, 1],
[-1, 0, 2, 0, -1],
[ 1, -4, 6, -4, 1]])
>>> f[1,:].T
matrix([[-1],
[-2],
[ 0],
[ 2],
[ 1]])
>>> np.dot(f[1, :].T, f[1, :])
matrix([[ 1, 2, 0, -2, -1],
[ 2, 4, 0, -4, -2],
[ 0, 0, 0, 0, 0],
[-2, -4, 0, 4, 2],
[-1, -2, 0, 2, 1]])
As this is the matrix class * will denote matrix multiplication, therefore you can simply use:
f[1,:].T * f[1,:]
Also you may want to consider np.outer for this kind of operation:
>>> np.outer(f[1,:],f[1,:])
array([[ 1, 2, 0, -2, -1],
[ 2, 4, 0, -4, -2],
[ 0, 0, 0, 0, 0],
[-2, -4, 0, 4, 2],
[-1, -2, 0, 2, 1]])
If you want the individual slices to retain their "matrixness" then you should cast f to a numpy.matrix, which preserves the matrixness.
fm = numpy.matrix(f)
then
numpy.dot(fm[1,:].T,fm[1,:])
will return an nxn matrix
Following the accepted answer, I prefer to use None instead of np.newaxis, which is a little verbose for my tastes. For example,
f[:,None]
does the same thing as f[:,np.newaxis].
I am late to the party here, it is worth noting that the NumPy webpage I accessed today warns that
class numpy.matrix(data, dtype=None, copy=True)
might be removed.