I'm encountering an issue with a Numba-optimized function that involves a custom class for representing a sparse matrix. The error message I'm getting is:
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
tuple index out of range
During: typing of static-get-item at z:\2023-2024\Python Labs\E0\TEST\Untitled-3.py (73)
File "z:\2023-2024\Python Labs\E0\TEST\Untitled-3.py", line 73:
def numba_csc_ndarray_dot2(a: csc_matrix, b: np.ndarray):
out = np.zeros((a.shape[0], b.shape[1]))
^
The problem seems to be related to indexing tuples, and it occurs in the following code snippet:
class csc_matrix:
def __init__(self, data: np.array, indices: np.array, indptr: np.array, shape: tuple):
self.data = data
self.indices = indices
self.indptr = indptr
self.shape = [email protected](nopython=True)
class MatrixType(types.Type):
def __init__(self, dtype):
self.dtype = dtype
self.data = types.Array(self.dtype, 1, 'C')
self.indices = types.Array(types.int64, 1, 'C')
self.indptr = types.Array(types.int64, 1, 'C')
self.shape = types.UniTuple(types.int64, 2)
super(MatrixType, self).__init__('csc_matrix')
@typeof_impl.register(csc_matrix)
def typeof_matrix(val, c):
data = typeof_impl(val.data, c)
return MatrixType(data.dtype)
@register_model(MatrixType)
class MatrixModel(models.StructModel):
def __init__(self, dmm, fe_type):
members = [('data', fe_type.data),('indices', fe_type.indices),('indptr', fe_type.indptr),('shape', fe_type.shape),]
models.StructModel.__init__(self, dmm, fe_type, members)
make_attribute_wrapper(MatrixType, 'data', 'data')
make_attribute_wrapper(MatrixType, 'indices', 'indices')
make_attribute_wrapper(MatrixType, 'indptr', 'indptr')
make_attribute_wrapper(MatrixType, 'shape', 'shape')
def make_matrix(context, builder, typ, **kwargs):
return cgutils.create_struct_proxy(typ)(context, builder, **kwargs)
@unbox(MatrixType)
def unbox_matrix(typ, obj, c):
data = c.pyapi.object_getattr_string(obj, 'data')
indices = c.pyapi.object_getattr_string(obj, 'indices')
indptr = c.pyapi.object_getattr_string(obj, 'indptr')
shape = c.pyapi.object_getattr_string(obj, 'shape')
matrix = make_matrix(c.context, c.builder, typ)
matrix.data = c.unbox(typ.data, data).value
matrix.indices = c.unbox(typ.indices, indices).value
matrix.indptr = c.unbox(typ.indptr, indptr).value
matrix.shape = c.unbox(typ.shape, shape).value
for att in [data, indices, indptr, shape]:
c.pyapi.decref(att)
is_error = cgutils.is_not_null(c.builder, c.pyapi.err_occurred())
return NativeValue(matrix._getvalue(), is_error=is_error)
@box(MatrixType)
def box_matrix(typ, val, c):
matrix = make_matrix(c.context, c.builder, typ)
classobj = c.pyapi.unserialize(c.pyapi.serialize_object(csc_matrix))
data_obj = c.box(typ.data, matrix.data)
indices_obj = c.box(typ.indices, matrix.indices)
indptr_obj = c.box(typ.indptr, matrix.indptr)
shape_obj = c.box(typ.shape, matrix.shape)
matrix_obj = c.pyapi.call_function_objargs(classobj, (data_obj, indices_obj, indptr_obj, shape_obj))
return matrix_obj
def numba_csc_ndarray_dot2(a: csc_matrix, b: np.ndarray):
out = np.zeros((a.shape[0], b.shape[1]))
for j in range(b.shape[1]):
for i in range(b.shape[0]):
for k in range(a.indptr[i], a.indptr[i + 1]):
out[a.indices[k], j] += a.data[k] * b[i, j]
rows, cols = 100, 100
density = 0.1
sparse_coo = random(rows, cols, density=density, format='coo')
data = sparse_coo.data
indices = sparse_coo.row
indptr = sparse_coo.col
shape = (rows, cols)
matrix_A = csc_matrix(sparse_coo.data, sparse_coo.row, sparse_coo.col, shape=(rows, cols))
vector_b = np.random.rand(cols)
solution_x =numba_csc_ndarray_dot2(matrix_A,vector_b )
print("Matrix A:")
print(matrix_A.toarray())
print("\nVector b:")
print(vector_b)
print("\nSolution x:")
print(solution_x)
I suspect that either a.indices[k] or a.data[k] is resulting in a tuple, causing the "tuple index out of range" error. I've added some debugging print statements, and the output indicates unexpected tuple values.
I'd appreciate any insights or suggestions on how to resolve this issue.