If I need to do multiplication between 5 matrix (taking into account the good shape of the matrix to be able to multiplicate), np.dot doesn't work. For ex, in matlab you can easily write:
Rf = T^-1 * S^-1 * R * S * T
to multiply two matrices you can use:
np.matmul(matrix1, matrix2).shape
then use for loop to multiply 5 matrices.
for more info check numpy documentation :
https://docs.scipy.org/doc/numpy/reference/generated/numpy.matmul.html
Related
I need to do simple calculation on matricies and vector using np.array and np.matrix. My problem is that I do not know what is the difference between np.array and np.matrix. Calculation do I need to do is (among others):
A - matrix
B - matrix
x - vector
1. A * x
2. A * B
3. (A * A^T)^-1
Once, I need to do in using np.array and again using np.matrix.
I have tried many ways like:
Ax = A.dot(x) # multiplication by vector
AB = np.dot(A, B) # multiplication by matrix
ab = np.matmul(A, B) # multiplication by matrix
At = A.transpose()
At = np.transpose(A)
inv = np.linalg.inv(a) # and inverse matrix, but I do not know which is np. matrix or np.array.
Kindly help.
Here's an answer clarifying the differences and the advantages of vectors and matrices.
It also explains multiplications between them.
I have a matrix A with shape=(N, N) and a matrix B with the same shape=(N, N).
I am constructing a matrix M using the following einsum (using the opt_einsum library):
M = oe.contract('nm,in,jm,pn,qm->ijpq', A, B, B, B, B)
This is evaluating the following sum:
This yeilds matrix M with shape (N, N, N, N). I then reshape this to a 2D array of shape (N**2, N**2)
M = M.reshape((N**2, N**2))
This must be 2D as it is treated as a linear operator.
I want to use the sparse library, as M is sparse, and becomes too large to store for large N. I can make A and B sparse, and insert them into the oe.contract.
The problem is, sparse only supports 2D arrays and so fails to produce the 4D output of shape (N, N, N. N). Is there a way to combine the einsum and reshape steps to allow sparse to be used in this way, as the final shape of M is 2D?
This may not help with your use of opt_einsum, but with a bit of reorganizing I can speed up np.einsum quite a bit, at least for small arrays.
Do a partial product of two B:
c1 = np.einsum('in,jm->ijnm',B,B).reshape(N*N,N,N)
The pq pair is the same, so we don't need to recalculate it:
c2 = np.einsum('nm,onm,pnm->op',A,c1,c1)
I verified that this works for two (3,3) arrays, and the speed up is about 10x.
We can even reshape the nm to 1d, though this doesn't improve speed:
c1 = np.einsum('in,jm->ijnm',B,B).reshape(N*N,N*N)
c3 = np.einsum('n,on,pn->op',A.reshape(N*N),c1,c1)
I did not correctly interpret the error given by opt_einsum.
The problem is not that sparse does not support ND sparse arrays (it does!), but that I was not using a true einsum, as the indices summed over appear more than twice (n and m). As stated in the opt_einsum documentation this will result in the use of the sparse.einsum function, of which none exists. Using only 1 or 2 of each index works. Using a differerent path, one suggested for example by hpaulj can be used to solve the problem.
I have a numpy array of matrices which i am trying to multiply together in the form A * B * C * D where A is the first matrix, B is the second and so on. I have tried this code:
matrix = matrices[0]
for m in matrices[1:]:
matrix = np.matmul(matrix, m)
However I believe this multiplication is wrong as i get incorrect output variables, and I have triple checked the rest of my code so I believe this is the issue. How can I multiply all the matrices in this array together? Also the array length will vary depending on the input file, thus i cant use an A * B * C approach.
Your code for multiply a series of matrices together should work. Here is an example using your method with some simple matrices.
import numpy as np
matrices = []
matrices.append(np.eye(3,dtype=float))
matrices.append(np.matrix('1.0,2.0,3.0;4.0,5.0,6.0;7.0,8.0,8.0'))
matrices.append(np.eye(3,dtype=float))
matrices.append(np.linalg.inv(np.matrix('1.0,2.0,3.0;4.0,5.0,6.0;7.0,8.0,8.0')))
matrix = matrices[0]
for m in matrices[1:]:
matrix = np.matmul(matrix, m)
print(matrix)
directmul = np.matmul(matrices[1],matrices[3])
print(np.subtract(matrix,directmul))
Your problem is somewhere else: maybe how you are filling the list of matrices, or how are you filling the matrices. Have you tried unit testing on your code? Have you give a try to the python debugger?
Psi is stored as a ND numpy array on a spacial grid (for example if N=2 Psi is a 2D array of complex values). What is the best way to use numpy to compute the following integral:
I assume it will be a combination of np.tensordot and np.sum, but I cannot find a way to do it without relying on some heavy loops (problematic for large N).
The solution is:
NI = 2*(N-1) # number of integrals
tensor = np.multiply.outer(psi, psi.conj())
for i in range(N):
axis = -1 if i < N/2 else -2
tensor = np.sum(tensor, axis=axis)
rho = tensor * dx**N
I have a linear system in which all the matrices are block diagonal. They have N blocks identical in shape.
Matrices are stored in compressed format as numpy arrays with shape (N, n, m), while the shape of the vectors is (N, m).
I currently implemented the matrix-vector product as
import numpy as np
def mvdot(m, v):
return (m * np.expand_dims(v, -2)).sum(-1)
Thanks to broadcasting rules, if all the blocks of a matrix are the same I have to store it only once in an array with shape (1, n, m): the product with a vector (N, m) still gives the correct (N, n) vector.
My questions are:
how to implement an efficient matrix-matrix product that yields the matrix with shape (N, n, m) from two matrices with shapes (N, n, p) and (N, p, m)?
is there a way to perform these operations with a numpy built-in (possibly faster) function? Functions like np.linalg.inv make me think that numpy was designed to support this compressed format for block diagonal matrices.
If I understand your question correctly, you have two arrays of shape (N,n,p) and (N,p,m), respectively, and their product should be of shape (N,n,m) where element [i,:,:] is the matrix product of M1[i,:,:] and M2[i,:,:]. This can be achieved using numpy.einsum:
import numpy as np
N = 7
n,p,m = 3,4,5
M1 = np.random.rand(N,n,p)
M2 = np.random.rand(N,p,m)
Mprod = np.einsum('ijk,ikl->ijl',M1,M2)
# check if all the submatrices are what we expect
all([np.allclose(np.dot(M1[k,...],M2[k,...]),Mprod[k,...]) for k in range(N)])
# True
Numpy's einsum is an incredibly versatile construction for complicated linear operations, and it's usually pretty efficient with two operands. The idea is to rewrite your operation in an indexed way: what you need is to multiply M1[i,j,k] with M2[i,k,l] for each i,j,l, and sum over k. This is exactly what the above call to einsum does: it collapses the index k, and performs the necessary products and assignments along the remaining dimensions in the given order.
The matrix-vector product can be done similarly:
M = np.random.rand(N,n,m)
v = np.random.rand(N,m)
Mvprod = np.einsum('ijk,ik->ij',M,v)
It's possible that numpy.dot can be coerced with the proper transposes and dimension tricks to directly do what you want, but I couldn't make that work.
Both of the above operations can be done in the same function call by allowing an implicit number of dimensions within einsum:
def mvdot(M1,M2):
return np.einsum('ijk,ik...->ij...',M1,M2)
Mprod = mvdot(M1,M2)
Mvprod = mvdot(M,v)
In case the input argument M2 is a block matrix, there will be a leading dimension appended to the result, creating a block matrix. In case M2 is a "block vector", the result will be a block vector.
Since Python 3.5 and above, the previous example can be simplified using the matrix multiplication operator # (numpy.matmul) which treats this case as a stack of matrices residing in the last two indexes and broadcast accordingly:
import numpy as np
N = 7
n,p,m = 3,4,5
M1 = np.random.rand(N,n,p)
M2 = np.random.rand(N,p,m)
Mprod = M1 # M2 # similar to np.matmul(M1, M2)
all([np.allclose(np.dot(M1[k,...],M2[k,...]),Mprod[k,...]) for k in range(N)])
#True