I want to obtain the bases for kernel (nullspace) of a matrix using the Row Reduced Echelon Form (RREF).
Although scipy has the function to calculate nullspace, it does not give me sparse vectors because it uses singular value decomposition (SVD).
#make an example
import random
import numpy as np
random.seed(1)
m=100
n=120
matrix = [1 if random.uniform(0, 1)>0.9 else 0 for i in range (m*n)]
matrix =np.array (matrix).reshape((m, n))
#calculate nullspace using scipy
from scipy import linalg
ns2=linalg.null_space(matrix)
print (ns2)#This is not sparse, which is not what I want to obtain.
Instead, I used the function in sympy.
import sympy
ns2=sympy.Matrix(matrix).nullspace()
if ns2:
ns2=np.concatenate([np.array(vec, dtype=float) for vec in ns2], axis=1)
print (ns2)
However, this takes a lot of time, probably because Sympy are struggling to find the algebraic solution.
So, I tried to use lambdify, which converts SymPy expressions into NumPy functions. This canbe wrapped with numba to make them faster, as suggested here. https://github.com/numba/numba/issues/4795
I tried to convert SymPy expressions into NumPy functions
f = sympy.lambdify(x, sympy.Matrix(np.array(x)).nullspace() , "numpy")
but this did not work.
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last) in ----> 1 f = sympy.lambdify(x, sympy.Matrix(np.array(x)).nullspace() , "numpy")
/opt/anaconda3/lib/python3.8/site-packages/sympy/matrices/dense.py in new(cls, *args, **kwargs) 297 298 def new(cls, *args, **kwargs): --> 299 return cls._new(*args, **kwargs) 300 301 @classmethod
/opt/anaconda3/lib/python3.8/site-packages/sympy/matrices/dense.py in _new(cls, copy, *args, **kwargs) 308 rows, cols, flat_list = args 309 else: --> 310 rows, cols, flat_list = cls._handle_creation_inputs(*args, **kwargs) 311 flat_list = list(flat_list) # create a shallow copy 312 self = object.new(cls)
/opt/anaconda3/lib/python3.8/site-packages/sympy/matrices/matrices.py in _handle_creation_inputs(cls, *args, **kwargs) 982 # Matrix(numpy.ones((2, 2))) 983 elif hasattr(args[0], "array"): --> 984 return cls._handle_ndarray(args[0]) 985 986 # Matrix([1, 2, 3]) or Matrix([[1, 2], [3, 4]])
/opt/anaconda3/lib/python3.8/site-packages/sympy/matrices/matrices.py in _handle_ndarray(cls, arg) 906 return arr.shape[0], 1, flat_list 907 else: --> 908 raise NotImplementedError( 909 "SymPy supports just 1D and 2D matrices") 910
NotImplementedError: SymPy supports just 1D and 2D matrices
Is there any ways to speed up the calculation?