I want to solve the following linear system for x
Ax = b
Where A is sparse and b is just regular column matrix. However when I plug into the usual np.linalg.solve(A,b) routine it gives me an error. However when I do np.linalg.solve(A.todense(),b) it works fine.
Question.
How can I use this linear solve still preserving the sparseness of A?. The reason is A is quite large about 150 x 150 and there are about 50 such matrices and so keeping it sparse for as long as possible is the way I'd prefer it.
I hope my question makes sense. How should I go about achieving this?
Use scipy instead to work on sparse matrices.You can do that using scipy.sparse.linalg.spsolve. For further details read its documentation spsolve
np.linalg.solve only works for array-like objects. For example it would work on a np.ndarray or np.matrix (Example from the numpy documentation):
import numpy as np
a = np.array([[3,1], [1,2]])
b = np.array([9,8])
x = np.linalg.solve(a, b)
or
import numpy as np
a = np.matrix([[3,1], [1,2]])
b = np.array([9,8])
x = np.linalg.solve(a, b)
or on A.todense() where A=scipy.sparse.csr_matrix(np.matrix([[3,1], [1,2]])) as this returns a np.matrix object.
To work with a sparse matrix, you have to use scipy.sparse.linalg.spsolve (as already pointed out by rakesh)
import numpy as np
import scipy.sparse
import scipy.sparse.linalg
a = scipy.sparse.csr_matrix(np.matrix([[3,1], [1,2]]))
b = np.array([9,8])
x = scipy.sparse.linalg.spsolve(a, b)
Note that x is still a np.ndarray and not a sparse matrix. A sparse matrix will only be returned if you solve Ax=b, with b being a matrix and not a vector.
Related
I'm looking to do fast matrix multiplication in python, preferably NumPy, of an array A with another array B of repeated matrices by using a third array I of indices. This can be accomplished using fancy indexing and matrix multiplication:
from numpy.random import rand, randint
A = rand(1000,5,5)
B = rand(40000000,5,1)
I = randint(low=0, high=1000, size=40000000)
A[I] # B
However, this creates the intermediate array A[I] of shape (40000000, 5, 5) which overflows the memory. It seems highly inefficient to have to repeat a small set of matrices for multiplication, and this is essentially a more general version of broadcasting such as A[0:1] # B which has no issues.
Are there any alternatives?
I have looked at NumPy's einsum function but have not seen any support for utilizing an index vector in the call.
If you're open to another package, you could wrap it up with dask.
from numpy.random import rand, randint
from dask import array as da
A = da.from_array(rand(1000,5,5))
B = da.from_array(rand(40000000,5,1))
I = da.from_array(randint(low=0, high=1000, size=40000000))
fancy = A[I] # B
After finished manipulating, then bring it into memory using fancy.compute()
Using from scipy.sparse.linalg import LinearOperator I want to determine the transpose of a <3x3 _CustomLinearOperator with dtype=float64>>. Consider the following random permutation of coordinate axes:
import numpy as np
from scipy.sparse.linalg import LinearOperator
n=3
x = np.arange(n)
np.random.shuffle(x)
def w(v):
n = len(v)
w = np.zeros((n,1))
for j in range(n):
w[j] = v[x[j]]
return np.array(w)
W = LinearOperator((n,n), matvec=w)
Note that W is an orthogonal matrix. W.tranpose leads to <bound method LinearOperator.transpose of <3x3 _CustomLinearOperator with dtype=float64>> but I don't know how to handle this method. What I would like to calculate is W.tranpose*W as <3x3 _CustomLinearOperator with dtype=float64>> but this of course is an unsupported operand type.
You need to define the transpose of the operator yourself otherwise it won’t know what operation to apply; you cannot assume that scipy would know what is the transpose of the operator of it even exist.
You can read in the following link:
https://www.google.com/amp/s/samrelton.wordpress.com/2013/12/04/implicit-matrices-in-python/amp/
Side note: you are trying to calculate the norm so once you define the transpose you’ll able to apply norm like functions
I've got linear system to solve which consists of large, sparse matrices.
I've been using the scipy.sparse library, and its linalg sub-library to do this, but I can't get some of the linear solvers to work.
Here is a working example which reproduces the issue for me:
from numpy.random import random
from scipy.sparse import csc_matrix
from scipy.sparse.linalg import spsolve, minres
N = 10
A = csc_matrix( random(size = (N,N)) )
A = (A.T).dot(A) # force the matrix to be symmetric, as required by minres
x = csc_matrix( random(size = (N,1)) ) # create a solution vector
b = A.dot(x) # create the RHS vector
# verify shapes and types are correct
print('A', A.shape, type(A))
print('x', x.shape, type(x))
print('b', b.shape, type(b))
# spsolve function works fine
sol1 = spsolve(A, b)
# other solvers throw a incompatible dimensions ValueError
sol2 = minres(A, b)
Running this produces the following error
raise ValueError('A and b have incompatible dimensions')
ValueError: A and b have incompatible dimensions
for the call to minres, even though the dimensions clearly are compatible. Other solvers in scipy.sparse.linalg, such as cg, lsqr and gmres all throw an identical error.
This is being run on python 3.6.1 with SciPy 0.19.
Anyone have any idea what's going on here?
Thanks!
Your usage is incompatible with the API!
spsolve on b:
b : ndarray or sparse matrix
The matrix or vector representing the right hand side of the equation. If a vector, b.shape must be (n,) or (n, 1).
sparse b is allowed
minres on b:
b : {array, matrix}
Right hand side of the linear system. Has shape (N,) or (N,1).
sparse b is not allowed here!
The same applies to the mentioned non-working solvers (where lsqr might be a bit different -> array_like vs. array).
This is not that uncommon as sparse rhs-vectors are not helping in many cases and a lot of numerical-optimization devs therefore drop support!
This works:
sol2 = minres(A, b.todense())
(you got my upvote and praise for the nice reproducible example!)
I'm looking for dynamically growing vectors in Python, since I don't know their length in advance. In addition, I would like to calculate distances between these sparse vectors, preferably using the distance functions in scipy.spatial.distance (although any other suggestions are welcome). Any ideas how to do this? (Initially, it doesn't need to be efficient.)
Thanks a lot in advance!
You can use regular python lists (which are dynamic) as vectors. Trivial example follows.
from scipy.spatial.distance import sqeuclidean
a = [1,2,3]
b = [0,0,0]
print sqeuclidean(a,b) # 14
As per aganders3's suggestion, do note that you can also use numpy arrays if needed:
import numpy
a = numpy.array([1,2,3])
If the sparse part of your question is crucial I'd use scipy for that - it has support for sparse matrixes. You can define a 1xn matrix and use it as a vector. This works (the parameter is the size of the matrix, filled with zeroes by default):
sqeuclidean(scipy.sparse.coo_matrix((1,3)),scipy.sparse.coo_matrix((1,3))) # 0
There are many kinds of sparse matrixes, some dictionary based (see comment). You can define a row sparse matrix from a list like this:
scipy.sparse.csr_matrix([1,2,3])
Here is how you can do it in numpy:
import numpy as np
a = np.array([1, 2, 3])
b = np.array([0, 0, 0])
c = np.sum(((a - b) ** 2)) # 14
Is it possible to apply for example numpy.exp or similar pointwise operators to all elements in a scipy.sparse.lil_matrix or another sparse matrix format?
import numpy
from scipy.sparse import lil_matrix
x = numpy.ones((10,10))
y = numpy.exp(x)
x = lil_matrix(numpy.ones((10,10)))
# y = ????
numpy.exp(x) or scipy.exp(x) yields an AttributeError, and numpy.exp(x.data) yields the same.
thanks!
I do not know the full details, but converting to another type works, at least when using the array of non zero elements:
xcsc = x.tocsc()
numpy.exp(xcsc.data) # works